前言
开心一刻
十年前, 我: 我交女票了, 比我大两岁. 妈: 不行! 赶紧分!
八年前, 我: 我交女票了, 个比我小两岁, 外地的. 妈: 你就不能让我省点心?
五年前, 我: 我交女票了, 市长的女儿. 妈: 别人还能看上你? 分了吧!
今年, 我挺着大肚子踏进家门. 妈: 闺女啊, 你终于开窍了 !
前情回顾
Spring 拓展接口之 BeanPostProcessor, 我们来看看它的底层实现中讲到了 spring 对 BeanPostProcessor 的底层支持, 并且知道了 BeanPostProcessor 的两个方法: postProcessBeforeInitialization,postProcessAfterInitialization 的执行时机, 没看的小伙伴可以回过头去看看. 本来 spring 的自动装配是打算放到上一篇博文中详细讲解的, 可后来觉得篇幅可能太大了(细心的小伙伴可能会有这样的表情:, 除了几幅图, 真没什么内容!), 既然你们都感觉出来了, 那我也就明人不说暗话了, 之所以没放到上篇讲解, 确实是因为篇幅太大了(哈哈哈, 是不是很想打我? ); 好了, 我们言归正传, 之所以没放到上篇来讲, 篇幅只是原因之一, 最主要的原因是发现我犯错了! 犯什么错了呢(不是黄赌毒啊, 那是犯罪, 我是正人君子!), 我想当然了! 理所当然的认为自动装配是在 AutowiredAnnotationBeanPostProcessor 的 postProcessBeforeInitialization 或 postProcessAfterInitialization 中实现的, 我们来看下 AutowiredAnnotationBeanPostProcessor 类继承图
它间接实现了 BeanPostProcessor, 我们再去看下那两个方法(在父类 InstantiationAwareBeanPostProcessorAdapter 中)
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- return bean;
- }
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- return bean;
- }
- View Code
竟然啥也没干, 只是简单的 return bean; 当自己深以为然的认知被推翻时, 那感觉真是毙了狗了 所以自动装配不能和 BeanPostProcessor 放一块讲, 不得不开两篇来分开讲, 我们都知道: 强扭的瓜不甜!
自动装配简单示例
我们先来看一个简单的自动装配的示例, 完整实例代码: spring-boot-BeanPostProcessor
AnimalConfig
View Code
AnimalServiceImpl
- @Service
- public class AnimalServiceImpl implements IAnimalService {
- @Autowired
- private Dog dog;
- @Resource
- private Cat cat;
- @Inject
- private Pig pig;
- @Override
- public void printName() {
- System.out.println(dog.getName());
- System.out.println(cat.getName());
- System.out.println(pig.getName());
- }
- }
- View Code
- AnimalTest
- @RunWith(SpringRunner.class)
- @SpringBootTest(classes={Application.class})
- public class AnimalTest {
- @Autowired
- private IAnimalService animalService;
- @Test
- public void test() {
- animalService.printName();
- }
- }
- View Code
运行结果
我们在 AnimalConfig 中只是将 Dog,Cat,Pig 的实例注册到了 spring 容器, 那为什么 AnimalServiceImpl 实例能够直接应用这些实例了, 我们并没有手动的将这些实例赋值到 AnimalServiceImpl 实例呀? 这其实就是 spring 提供的自动装配功能, 虽然我们没有手动的将这些实例赋值到 AnimalServiceImpl 实例, 但是我们发现 AnimalServiceImpl 的属性实例上多了一些注解:@Autowired,@Resource,@Inject,spring 通过这些注解自动完成了属性实例的注入, 而不需要我们手动的去赋值了; 那么 spring 是如何实现自动装配的呢? 我们慢慢往下看(注意: 后文主要以 @Autowired 为例来讲解)
自动装配源码解析
AutowiredAnnotationBeanPostProcessor 的实例化与注册
不管怎么说, AutowiredAnnotationBeanPostProcessor 终归还是一个 BeanPostProcessor, 那么它的实例化与注册 (注册到 spring 的 beanFactory) 过程与 BeanPostProcessor 的实例化与注册一样, 在 spring 的启动过程中, 刷新上下文 (refresh) 的时候, 会调用 registerBeanPostProcessors(beanFactory)方法完成 BeanPostProcessor 的实例化与注册, 后续再调用 finishBeanFactoryInitialization(beanFactory)实例化非延迟加载的单例 bean 时, 会用到上述注册的 BeanPostProcessor
AutowiredAnnotationBeanPostProcessor 的构造方法值得我们看看
- public AutowiredAnnotationBeanPostProcessor() {
- this.autowiredAnnotationTypes.add(Autowired.class);
- this.autowiredAnnotationTypes.add(Value.class);
- try {
- this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
- ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
- logger.info("JSR-330'javax.inject.Inject'annotation found and supported for autowiring");
- }
- catch (ClassNotFoundException ex) {
- // JSR-330 API not available - simply skip.
- }
- }
- View Code
默认情况下, AutowiredAnnotationBeanPostProcessor 支持 @Autowired 和 @Value, 如果类路径下有 java.inject.Inject(也就是引入了 javax.inject.jar), 那么也支持 @Inject 注解, 是不是与我们最初的认知有些不一样?. 将支持的注解放到了 autowiredAnnotationTypes 属性中, 后续会用到该属性
bean 的实例化与依赖注入
默认情况下, spring 会把 spring 容器中的 bean 当成 non-lazy-init singleton 来处理(有些特殊的 bean 除外), 也就是说会在 spring 的启动过程中就会逐个实例化这些 bean, 并对这些 bean 进行依赖注入; 当我们真正用到这些 bean 的时候, 直接用就行, 不用再去实例化, 也不用再去注入 bean 的相关依赖, spring 是不是很厉害?. 具体是不是说的这样, 大家准备好花生, 瓜子和啤酒, 好戏即将开始
我们先找到正确的入口, 然后用下图省略掉无聊的前戏, 直接进入高潮: doCreateBean(不应该是这个吗, 一天天的尽胡思乱想)
doCreateBean 内容如下
- protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
- throws BeanCreationException {
- // Instantiate the bean.
- BeanWrapper instanceWrapper = null;
- if (mbd.isSingleton()) {
- instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
- }
- if (instanceWrapper == null) {
- // 创建 bean 实例
- instanceWrapper = createBeanInstance(beanName, mbd, args);
- }
- final Object bean = instanceWrapper.getWrappedInstance();
- Class<?> beanType = instanceWrapper.getWrappedClass();
- if (beanType != NullBean.class) {
- mbd.resolvedTargetType = beanType;
- }
- // Allow post-processors to modify the merged bean definition.
- // 允许后置处理器来修改 bean 定义
- synchronized (mbd.postProcessingLock) {
- if (!mbd.postProcessed) {
- try {
- // 调用 MergedBeanDefinitionPostProcessor 的 postProcessMergedBeanDefinition 方法
- // AutowiredAnnotationBeanPostProcessor 实现了 MergedBeanDefinitionPostProcessor, 即 MergedBeanDefinitionPostProcessor 的 MergedBeanDefinitionPostProcessor 会被调用
- applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
- }
- catch (Throwable ex) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "Post-processing of merged bean definition failed", ex);
- }
- mbd.postProcessed = true;
- }
- }
- // Eagerly cache singletons to be able to resolve circular references 立即缓存单例以便能够解析循环引用
- // even when triggered by lifecycle interfaces like BeanFactoryAware.
- boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
- isSingletonCurrentlyInCreation(beanName));
- if (earlySingletonExposure) {
- if (logger.isDebugEnabled()) {
- logger.debug("Eagerly caching bean'" + beanName +
- "'to allow for resolving potential circular references");
- }
- addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
- }
- // Initialize the bean instance.
- Object exposedObject = bean;
- try {
- // 填充 bean, 包含依赖注入
- populateBean(beanName, mbd, instanceWrapper);
- // 初始化 bean,BeanPostProcessor 的两个方法在此中被调用
- exposedObject = initializeBean(beanName, exposedObject, mbd);
- }
- catch (Throwable ex) {
- if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
- throw (BeanCreationException) ex;
- }
- else {
- throw new BeanCreationException(
- mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
- }
- }
- if (earlySingletonExposure) {
- Object earlySingletonReference = getSingleton(beanName, false);
- if (earlySingletonReference != null) {
- if (exposedObject == bean) {
- exposedObject = earlySingletonReference;
- }
- else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
- String[] dependentBeans = getDependentBeans(beanName);
- Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
- for (String dependentBean : dependentBeans) {
- if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
- actualDependentBeans.add(dependentBean);
- }
- }
- if (!actualDependentBeans.isEmpty()) {
- throw new BeanCurrentlyInCreationException(beanName,
- "Bean with name'" + beanName + "'has been injected into other beans [" +
- StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
- "] in its raw version as part of a circular reference, but has eventually been" +
- "wrapped. This means that said other beans do not use the final version of the" +
- "bean. This is often the result of over-eager type matching - consider using" +
- "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
- }
- }
- }
- }
- // Register bean as disposable.
- try {
- registerDisposableBeanIfNecessary(beanName, bean, mbd);
- }
- catch (BeanDefinitionValidationException ex) {
- throw new BeanCreationException(
- mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
- }
- return exposedObject;
- }
- View Code
我们重点看下 posProcessMergedBeanDefinition 方法和 populateBean 方法
posProcessMergedBeanDefinition
可以看到会读取 bean 的 field 和 method 上的注解, 并判断该注解是否在 autowiredAnnotationTypes 中, 如果在则将 field 封装成 AutowiredFiledElement 对象, 将 method 封装成 AutoWiredMethodElement 对象, 并存放到 InjectionMetadata 对象的 Set checkedElements 属性中, 最后将该 InjectionMetadata 对象缓存到了 AutowiredAnnotationBeanPostProcessor 的 Map
populateBean
调用 AutowiredAnnotationBeanPostProcessor 的 postProcessPropertyValues 方法, 从 injectionMetadataCache 中获取当前 bean 的依赖信息, 比如 animalServiceImpl 依赖的 dog,pig(有人可能会有这样的疑问: cat 呢? cat 是被 @Resource 修饰的, 而 @Resource 不是由 AutowiredAnnotationBeanPostProcessor 支持, 后续会讲由谁支持), 然后逐个将依赖 bean 注入到目标 bean(将 dog,pig 实例注入到 animalServiceImpl 实例中); 依赖 bean 从哪来呢? 还是从 beanFactory 中获取, 如果不存在, 则又回到 bean 的创建过程把依赖 bean(dog,pig)创建出来, 流程与创建 animalServiceImpl 实例一模一样, 也就说在 animalServiceImpl 实例的依赖注入过程中会把 dog,pig 对象也创建出来, 而不是等到 spring 逐个实例化 bean 的过程中轮到 dog,pig 才实例化 dog,pig, 那后续轮到 dog,pig 时怎么办了, spring 会把创建的 bean 缓存起来, 下次就直接从缓存中取了. 上图只演示 Field 的, Method 也差不太多, 就不演示了, 都是通过反射实现的 .
总结
1,bean 的创建与初始化
(1)instanceWrapper = createBeanInstance(beanName, mbd, args) 创建目标 bean 实例;
(2)applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName) 寻找目标 bean 的依赖;
(3)populateBean(beanName, mbd, instanceWrapper) 填充目标 bean, 完成依赖注入; (这里的循环依赖, 有兴趣的可以自行去琢磨下)
(4)initializeBean(beanName, exposedObject, mbd) 初始化目标 bean
2, 自动装配与自动配置
自动配置一般而言说的是 spring 的 @Autowired, 是 spring 的特性之一, 而自动配置是 springboot 的 @Configuration, 是 springboot 的特性之一
3,Spring 支持几下几种自动装配的注解
@Autowired,@Inject,@Resource 以及 @Value, 用的最多的应该是 @Autowired(至少我是这样的),@Inject 和 @Value 也是由 AutowiredAnnotationBeanPostProcessor 支持, 而 @Resource 是由 CommonAnnotationBeanPostProcessor 支持(还支持 @PostConstruct,@PreDestroy 等注解)
关于 @Value 与 @Autowired, 不知道大家是否清楚他们之间的区别, 不清楚的可以看看: Spring: @Value vs. @Autowired 或者 spring 的官方文档, 总结下:@Value>= @Autowired, 只是平时应用中,@Value 更多的是用来注入配置值(如:@Value("${db.url}")), 而 @Autowired 则是 bean 对象的注入
参考
JAVA 注解的基本原理 https://juejin.im/post/5b45bd715188251b3a1db54f
深入理解 Spring 系列之十四:@Autowired 是如何工作的 https://juejin.im/entry/5ad3fda5f265da238d512a98
来源: https://www.cnblogs.com/youzhibing/p/11031216.html