源码这里就不再贴了,因为确实比较简单。用一些文字描述即可:
1.invokeAwareMethods:执行一些感知接口Aware的注入
2. postProcessBeforeInitialization:执行后置处理器的此方法。基本上也是执行一些Aware的注入。
—>1. InitDestroyAnnotationBeanPostProcessor在这里会执行@PostConstruct标记的方法
—>2. ApplicationContextAwareProcessor/ServletContextAwareProcessor会实现感知接口的注入
4. invokeInitMethods:先执行InitializingBean#afterPropertiesSet方法,再执行init-method。
5. postProcessAfterInitialization:执行后置处理器此方法。这里面有不少干实事的:
—>1. AbstractAdvisingBeanPostProcessor,AbstractAutoProxyCreator:会把所有的切面保存下来(AOP包下的)
—>2. ApplicationListenerDetector:会把所有的ApplicationListener子类保存起来
—>3. ScheduledAnnotationBeanPostProcessor:会把所有的标注了@Scheduled的方法保存起来
—>4. SimpleServletPostProcessor:会调用Servlet#init的init方法
至于对应的@EventListener注解是什么时候解析的。是它:EventListenerMethodProcessor,它是一个SmartInitializingSingleton,所以它是在preInstantiateSingletons()方法的最后一步去调用的(比如getBean()方法还晚)
由此,我们是可以得出结论的:Spring之外的Bean,SmartInitializingSingleton接口对他是不起作用的。但是,其余的处理器、注解等等都是有用的哦:@PostConstruct、@Autowired等等注解
就这样,就完成结束了我们的Bean的创建、实例化、初始化等等操作。
其它API:autowireBean、configureBean等等
autowireBean:
@Override public Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException { // Use non-singleton bean definition, to avoid registering bean as dependent bean. final RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck); bd.setScope(BeanDefinition.SCOPE_PROTOTYPE); if (bd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR) { return autowireConstructor(beanClass.getName(), bd, null, null).getWrappedInstance(); } else { Object bean; final BeanFactory parent = this; if (System.getSecurityManager() != null) { bean = AccessController.doPrivileged((PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(bd, null, parent), getAccessControlContext()); } else { bean = getInstantiationStrategy().instantiate(bd, null, parent); } populateBean(beanClass.getName(), bd, new BeanWrapperImpl(bean)); return bean; } }
和createBean的区别:createBean是全量的。什么各种后置处理器都不执行。而autowire它直接调用策略器实例化了,什么有关实例化的处理器就都不会执行了(所以不能生成代理对象了嘛)(使用较少,但可以绕过一些处理器)
autowireBeanProperties: 相当于只执行了给属性赋值populateBean()(以及相关的处理器)
@Override public void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException { // 构造器注入的模式,这里就不能支持了 if (autowireMode == AUTOWIRE_CONSTRUCTOR) { throw new IllegalArgumentException("AUTOWIRE_CONSTRUCTOR not supported for existing bean instance"); } // Use non-singleton bean definition, to avoid registering bean as dependent bean. RootBeanDefinition bd = new RootBeanDefinition(ClassUtils.getUserClass(existingBean), autowireMode, dependencyCheck); bd.setScope(BeanDefinition.SCOPE_PROTOTYPE); BeanWrapper bw = new BeanWrapperImpl(existingBean); initBeanWrapper(bw); populateBean(bd.getBeanClass().getName(), bd, bw); }
public static void main(String[] args) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(RootConfig.class); // ApplicationContext里面是持久AutowireCapableBeanFactory这个工具的,它真实的实现类一般都是:DefaultListableBeanFactory AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory(); //我们也可以自己手动创建一个实例 然后让Spring帮我们自动装配就行 也能正常注入 Child child = new Child(); autowireCapableBeanFactory.autowireBeanProperties(child, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false); System.out.println(child.getHelloService()); //com.fsx.service.HelloServiceImpl@175c2241 }
initializeBean:相当于只执行了初始化Bean的一些操作。。。
@Override public Object initializeBean(Object existingBean, String beanName) { return initializeBean(beanName, existingBean, null); }
…
…
…
后面的就不一一介绍了,因为有了上面的源码分析,了解其它的就不难了。
AutowireCapableBeanFactory的使用场景
1、首先最大的使用场景就是Spring内部
2、Spring Boot集成Quartz的时候。很好的使用到了此方案。我们在Job类里面使用@Autowired注入的时候,若出现注入不进去的现象。可以考虑使用AutowireCapableBeanFactory进行协助
3、前面说到的继承特定的第三方框架,他们的Bean并不需要交给Spring管理,但是又想用到Spring容器里面的Bean完成一些功能的时候,使用它就特别的方便了。
InstantiationStrategy
本来该策略接口不准备放在此处,但是正所谓说过的话,跪着也要走完啊(上面说过)。因此,那就来吧~
上面分析我们发现,Bean大都最终的实例化操作是交由这个策略器来搞定的,那它是什么呢?
// Interface responsible for creating instances corresponding to a root bean definition. // 简而言之,就是根据RootBeanDefinition,去实例化一个实例(相当于new了一个对象而已,bean的具体的属性在此时并未赋值) public interface InstantiationStrategy { // 下面是他的三个重载方法 // owner:这个Bean定义所属的BeanFactory工厂 // args:构造函数的参数(大多数情况下都用无参构造) // factoryBean:factoryMethod 也支持工厂方法方式创建实例(注意此factoryBean非我们所常指的接口:FactoryBean哦~) Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) throws BeansException; Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, Constructor<?> ctor, @Nullable Object... args) throws BeansException; Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, @Nullable Object factoryBean, Method factoryMethod, @Nullable Object... args) throws BeansException; }
它的继承结构很简单:
SimpleInstantiationStrategy
简单实现类,采用实现部分,抽象部分的策略(但是它可不是抽象类,因为我们是可以直接使用它的(如果没有方法注入MethodInjection的去求的话)。只是我们一般都不会直接使用它,而是子类
它的源码逻辑比较简单,伪代码如下:
if (!bd.hasMethodOverrides()) { ... // 最后:借助BeanUtils.instantiateClass(ctor, args) 利用构造函数创建实例 } else { return instantiateWithMethodInjection(bd, beanName, owner, ctor, args); }
CglibSubclassingInstantiationStrategy
留下了包含MethodOverride对象的bd对象定义未做实现,那么CglibSubclassingInstantiationStrategy就是它的一个实现:它采用采用cglib生成之类方式,实例化对象。(当然若不需要生成代理对象,就直接使用父类的功能即可的)
它的源码相对来说比较复杂:主要是静态内部类CglibSubclassCreator它生成一个子类对象去实现方法注入的功能,它内部有cglib动态代理的内容,这里确实就不太适合展开了,AOP再相见吧~
关于方法注入(MethodInjection):
当我们在一个bean中依赖其他的bean时,我们可以注入其他依赖的bean通过set()或者构造器方法。 这样调用get方法的时候返回在bean中注入的实例。但是如果我们希望在每次调用get方法的时候返回新的实例,怎么办呢?
比如单例的A,希望每次使用B的时候都是一个新的对象~
有的伙伴可能就会这么写了:
@Component public class A { @Autowired private B b; public B getB() { return b; } } @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) // 这里scope指定不是单例 public class B { } public static void main(String[] args) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(RootConfig.class); A a = applicationContext.getBean(A.class); // 我们发现,虽然我们给B设置成`prototype`,但是从a里面get出来的每次都还是同一个对象 System.out.println(a.getB() == a.getB()); //true //证明B不是单例了: B b1 = applicationContext.getBean(B.class); B b2 = applicationContext.getBean(B.class); //证明B并不是单例的 System.out.println(b1 == b2); //false }
现在,这个没达到我们的需求嘛。因为每次A类里面使用B的时候,还是同一个实例~
原因:因为A是单例,它只会被实例化一次,因此对应的属性也会被注入一次。所以即使你get()调用了多次,返回的还是第一次赋值的那个属性值
怎么办呢?、这个时候方法注入闪亮登场,我们只需要在A的get方法上加上@Lookup注解,在看看效果:
@Component public class A { @Autowired private B b; @Lookup // 采用方法注入 public B getB() { return b; } } public static void main(String[] args) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(RootConfig.class); A a = applicationContext.getBean(A.class); // 不仅仅每次getB都不一样了,我们还发现a已经变成了一个CGLIB的代理对象 System.out.println(a); //com.fsx.bean.A$$EnhancerBySpringCGLIB$$558725dc@6a6cb05c System.out.println(a.getB() == a.getB()); //false }
一下子就解决问题了。在上面分析的时候我们看到AbstractAutowireCapableBeanFactory默认采用的创建Bean策略器为
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
因此默认就是支持方法注入的,所以当我们方法标注了@Lookup注解,就能达到我们上诉的效果了~
了解了此处,对后续AOP原理讲解的时候,也有非常大的帮助~~~ 看来提前讲解还是不亏的,哈哈
总结
AutowireCapableBeanFactory接口给我们最大的感觉就是:交给Spring管理的Bean,关于Bean的创建、实例化、初始化等都是自动挡。而我们使用此接口可以拆解成手动档,自己来控制Bean的一些行为。
能够有如此的灵活性,还是得益于Spring的分层设计、组件化的、可插拔等等一些设计特针。再次向Spring的设计者致敬,给这个行业做出的巨大贡献~
另外本文分析中,还有些小细节是需要注意的:比如@Autowired注解不是必须的,交给Spring容器管理也不是必须的,所以建议能够了解到每段代码、注解、处理器的具体执行时机,很多问题就迎刃而解了。