如何为脱离Spring IOC容器管理的Bean赋能【依赖注入的能力】
不可否认的是,把Bean交给Spring管理,确实极其的方便,优点一大把,并且还几乎没有啥缺点。这也就是为何咱们一言不合就把Bean扔给Spring的原因。(在Spring的技术栈里这么做,完全没有问题)
然而,就Spring框架本身而言。它的强大的依赖注入,不仅仅能给自家的Bean使用,还能赋能给容器之外的Bean,快速的把需要注入的对象给它装配好。
AutowireCapableBeanFactory 的解释
* Extension of the {@link org.springframework.beans.factory.BeanFactory}
* interface to be implemented by bean factories that are capable of
* autowiring, provided that they want to expose this functionality for
* existing bean instances.
AutowireCapableBeanFactory在BeanFactory基础上实现了对存在实例的管理,可以使用这个接口集成其它框架,捆绑并填充并不由Spring管理生命周期并已存在的实例。像集成WebWork的Actions 和Tapestry Page就很实用。
public interface AutowireCapableBeanFactory extends BeanFactory {
int AUTOWIRE_NO = 0;
int AUTOWIRE_BY_NAME = 1;
int AUTOWIRE_BY_TYPE = 2;
int AUTOWIRE_CONSTRUCTOR = 3;
@Deprecated
int AUTOWIRE_AUTODETECT = 4;
// 注意这个CreateBean和下面的CrateBean的不同
//JavaDoc:It does <i>not</> imply traditional by-name or by-type autowiring of properties;
// 也就是说它只管给你创建Bean,但是不管给你根据Name或者Type进行注入哦
// 当然,你可以显示在对应属性上指定@Autowired注解,让他也可以达到相同的效果
<T> T createBean(Class<T> beanClass) throws BeansException;
void autowireBean(Object existingBean) throws BeansException;
Object configureBean(Object existingBean, String beanName) throws BeansException;
Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck)
throws BeansException;
void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException;
Object initializeBean(Object existingBean, String beanName) throws BeansException;
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException;
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException;
void destroyBean(Object existingBean);
<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;
@Nullable
Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException;
@Nullable
Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException;
}
以createBean() 方法为例
// 准备一个Child类
@Getter
@Setter
public class Child {
// 注意:这里并没有@Autowired注解的
private HelloService helloService;
private String name;
private Integer age;
}
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(RootConfig.class);
// ApplicationContext里面是持久AutowireCapableBeanFactory这个工具的,它真实的实现类一般都是:DefaultListableBeanFactory
AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();
// 我把Child的创建过程都交给Bean工厂去帮我们处理,自己连new都不需要了 (createBean方法执行多次,就会创建多个child实例)
Child child = (Child) autowireCapableBeanFactory.createBean(Child.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
//简直残暴,没有@Autowired注解都给注入进来了~~~ 至于为什么,看看下面的分析,你就知道了
System.out.println(child.getHelloService()); //com.fsx.service.HelloServiceImpl@6a78afa0
// 抛出异常 No qualifying bean of type 'com.fsx.bean.Child' available
// 能佐证:我们的Bean并没交给Spring容器管理,它只是帮我们创建好了,并把对应属性注入进去了
Child bean = applicationContext.getBean(Child.class);
System.out.println(bean);
}
看到这个现象有没有很惊喜,我们哪怕不是Spring去管理的对象,都能够依赖注入进来容器内的对象,并且连@Autowired注解都不需要。所以更别谈Spring内部的容器,并且还标注了注解的,那就应该更容易去实现了
以createBean() 方法为例的源码分析
AbstractAutowireCapableBeanFactory#createBean:
@Override
public Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
// 这里看到了,采用的不是单例,而是prototype
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
// For the nullability warning, see the elaboration in AbstractBeanFactory.doGetBean;
// in short: This is never going to be null unless user-declared code enforces null.
// doc说得很明白,这里返回值永远不可能为null。除非调用者强制return null
// 注意的是:这里BeanName就是beanClass.getName()
return createBean(beanClass.getName(), bd, null);
}
// 最终都调用到了下面这个createBean方法。它也是AbstractBeanFactory提供的一个抽象方法
// 最终也由AbstractAutowireCapableBeanFactory去实现的。 我们熟悉的doGetBean()方法,最终也是调用它来创建实例对象 只是doGetBean()把单例对象都缓存起来了
// 这个方法很单纯:创建一个实例,然后初始化他(给属性们赋值),然后return出去即可
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
// 解析一些@lookup注解之类的 忽略
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 这个之前都解释过了,就不解释了。若BeanPostProcessors 产生了一个代理对象,就不需要我去创建了,就不继续往下走了(AOP都走这里)
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 重点来了。它是本类的一个protected方法,专门用于处理创建Bean的过程(包括属性赋值之类的)
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
这里再看看doCreateBean吧,因为之前有讲过这个方法,这里就只看核心步骤。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args){
BeanWrapper instanceWrapper = null;
...
//createBeanInstance 是重点(都是返回一个BeanWrapper) 它也是本类的一个protected方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
// Bean已经实例化好了,准备初始化吧
...
// 执行MergedBeanDefinitionPostProcessor
// 处理循环引用,现在若我们Bean不在容器里,肯定是不存在循环引用的(但是我依赖的Bean可能还没创建是真的,也是这里来处理的)
...
// 给Bean实例的各个属性进行赋值 比如调用InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation、给属性注入值(并不依赖于@Autowired注解)
// 执行InstantiationAwareBeanPostProcessor#postProcessPropertyValues等等
populateBean(beanName, mbd, instanceWrapper);
// 初始化Bean 执行一些初始化方法init @PostContruct方法等等
//BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization等等
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
综上可以看出,目前最重要的三个步骤为doCreateBean里面的:createBeanInstance、populateBean、initializeBean,都在AbstractAutowireCapableBeanFactory这里
createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 如果不为null,并且还不是public的访问权限 并且还nonPublicAccessAllowed为false 那就抛异常吧
// 题外话:nonPublicAccessAllowed为true的情况下(默认值),即使你不是public的也ok
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
// 你可以自己通过Supplier来创建Bean,最终交给obtainFromSupplier包装成BeanWrapper
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//通过工厂方法创建 支持工厂方法方式创建Bean
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
//一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器
//在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 首次进入,resolved为false。
// 说一下:ConstructorResolver,就是找到合适的构造器给你去实例化一个Bean(会结合Spring容器进行一起解析)
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
// Need to determine the constructor...
// 执行BeanPostProcesso#determineCandidateConstructors 自己去决定使用哪个构造器,可能会返回一批构造器哟
// 这里我们很熟悉的`AutowiredAnnotationBeanPostProcessor`就实现了这个方法,可以智能去找出一个合适的构造器.
// 这里需要注意了,因为我们的Child的属性HelloService里并没有书写@Autowired属性,所以这里最终的返回结果是null================这个需要注意Spring的处理(空构造就不用交给autowireConstructor处理了,自己直接new吧)
// 需要注意的是:若我们自己写了一个构造 public Child(HelloService helloService) { this.helloService = helloService; } 那么它就会拿到,然后走下面让Spring执行构造器的注入的
// 旁白:如果你只有空构造,那就直接instantiateBean,否则会自动去走Spring的构造器注入的逻辑
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
// 所以我们当前的Child,只有空构造器,所以就只能走这里啦
// 这个方法的逻辑比较简单,我就不贴了。主要是用InstantiationStrategy策略器进行实例化,至于它是什么东东?文末的时候我会解释的
return instantiateBean(beanName, mbd);
}
该方法执行完成之后,我们对象就被创建了,但仅仅还只是创建好。下面继续看:
populateBean: 给Bean的各个属性赋值
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
boolean continueWithPropertyPopulation = true;
// 因为已经实例化了,对象已经创建了,所以这里立马执行了InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation方法
// 单反只有其中一个返回了false,相当于告诉容器我都处理好了,那么后面的赋值操作就Spring容器就不再处理了
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
//以对象的方式存储健值对,比存储在map会更加灵活
//PropertyValues 是用来管理PropertyValue的 一般情况下为null
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 那么接下来,就开始干正事了~~~~
// 这里需要注意的是:我们知道上面我们自己传进来的是byType,所以这个的if是能够进来的,最终能够定位autowireByType让它去实现注入功能。
//所以我们的helloService字段要不要@Autowired要不要无所谓(要了也只是重复操作而已,但是我建议显示的指明吧)
//但是被Spring扫描Scan管理的Bean们(或者其余Bean),如果你想要给他字段注入属性值,必须必须使用@Autowired注解,从而交给后置处理器AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues这个方法去处理
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
// 按类型自动装配。一般都会走这里,通过类型的匹配,来给属性赋值,实现注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
// 它的步骤相对简单:显示BeanUtils.getWriteMethodParameter(pd)拿到set方法(所以,这里需要注意,若没有set方法,这里是注入不进去的,这个没@Autowired强大)
// 然后去解析去容器里面找对应的依赖,也是resolveDependency方法(最终由DefaultListableBeanFactory去实现的)
// 这里需要注意:注入的时候isSimpleProperty不会被注入的(包括基本数据类型、Integer、Long。。。
//甚至还包括Enum、CharSequence(显然就包含了Spring)、Number、Date、URI、URL、Locale、Class等等)
// 但是,但是,但是标注@Autowired是能够注入的哦,哪怕是String、Integer等等
// 标注了@Autowired,没有找到反倒为报错 No qualifying bean of type 'java.lang.String' 。。。注意这些区别
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 开始执行InstantiationAwareBeanPostProcessor#postProcessPropertyValues
// 这里主要施工的又是我们大名鼎鼎的AutowiredAnnotationBeanPostProcessor它了,他会根据所有标注有@Autpwired注解地方,执行注入(非常重要)
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
//applyPropertyValues和PropertyValues密切相关,在后面相关专题在详细讲解 会回到这里的,持续关注~
// 作用:Apply the given property values, resolving any runtime references
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
至此,一个Bean的实例化、初始化操作可以完成了一大部分了(各字段、属性的赋值也都已经ok了~),那么还剩下一些收尾工作:比如init方法、post-construct方法之类的,就交给
initializeBean: 初始化Bean(调用一些初始化方法)
- invokeAwareMethods:执行一些感知接口Aware的注入
- postProcessBeforeInitialization:执行后置处理器的此方法。基本上也是执行一些Aware的注入。
- InitDestroyAnnotationBeanPostProcessor在这里会执行@PostConstruct标记的方法
- ApplicationContextAwareProcessor/ServletContextAwareProcessor会实现感知接口的注入
- invokeInitMethods:先执行InitializingBean#afterPropertiesSet方法,再执行init-method。
- postProcessAfterInitialization:执行后置处理器此方法。这里面有不少干实事的:
- AbstractAdvisingBeanPostProcessor,AbstractAutoProxyCreator:会把所有的切面保存下来(AOP包下的)
- ApplicationListenerDetector:会把所有的ApplicationListener子类保存起来
- ScheduledAnnotationBeanPostProcessor:会把所有的标注了@Scheduled的方法保存起来
- SimpleServletPostProcessor:会调用Servlet#init的init方法
至于对应的@EventListener注解是什么时候解析的。是EventListenerMethodProcessor,它是一个SmartInitializingSingleton,所以它是在preInstantiateSingletons()方法的最后一步去调用的(比getBean()方法还晚)。由此,我们是可以得出结论的:Spring之外的Bean,SmartInitializingSingleton接口对它是不起作用的。但是,其余的处理器、注解等等都是有用的,比如@PostConstruct、@Autowired等等注解。
就这样,就完成结束了我们的Bean的创建、实例化、初始化等等操作。
其他API
autowire bean
@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的使用场景
- 首先最大的使用场景就是Spring内部
- Spring Boot集成Quartz的时候。很好的使用到了此方案。我们在Job类里面使用@Autowired注入的时候,若出现注入不进去的现象。可以考虑使用AutowireCapableBeanFactory进行协助
- 前面说到的继承特定的第三方框架,他们的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
简单实现类,采用实现部分,抽象部分的策略(但是它可不是抽象类,因为我们是可以直接使用它的。只是我们一般都不会直接使用它,而是子类)
它的源码逻辑比较简单,伪代码如下:
if (!bd.hasMethodOverrides()) {
...
// 最后:借助BeanUtils.instantiateClass(ctor, args) 利用构造函数创建实例
} else {
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
CglibSubclassingInstantiationStrategy
留下了包含MethodOverride对象的bd对象定义未做实现,那么CglibSubclassingInstantiationStrategy就是它的一个实现:它采用cglib生成之类方式,实例化对象。(当然若不需要生成代理对象,就直接使用父类的功能即可的)
它的源码相对来说比较复杂:主要是静态内部类CglibSubclassCreator,它生成一个子类对象去实现方法注入的功能,它内部有cglib动态代理的内容。
关于方法注入(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 注解,就能达到我们上述的效果了~
总结
AutowireCapableBeanFactory接口给我们最大的感觉就是:交给Spring管理的Bean,关于Bean的创建、实例化、初始化等都是自动挡。而我们使用此接口可以拆解成手动档,自己来控制Bean的一些行为。
通过本文分析,这些小细节是需要注意的:比如@Autowired注解不是必须的,交给Spring容器管理也不是必须的,所以建议能够了解到每段代码、注解、处理器的具体执行时机,很多问题就迎刃而解了。
参考: |