万网网站建设的子分类能显示多少个,关键词排名查询工具免费,怎么做点击图片跳转网站,中山专业网站建设公司前言
之前我写过一篇关于BeanDefinition的文章,讲述了各个属性的作用,其中有一个属性我没有提到,因为这个属性比较重要,所以这里单独开一篇文章来说明
上一篇博文链接Spring之BeanDefinitionhttps://blog.csdn.net/qq_38257958/article/details/134823169?spm1001.2014.3001…前言
之前我写过一篇关于BeanDefinition的文章,讲述了各个属性的作用,其中有一个属性我没有提到,因为这个属性比较重要,所以这里单独开一篇文章来说明
上一篇博文链接Spring之BeanDefinitionhttps://blog.csdn.net/qq_38257958/article/details/134823169?spm1001.2014.3001.5501
再探AbstractBeanDefinition源码 通过源码我们得出结论,注入类型有四种
AUTOWIRE_NO (0)AUTOWIRE_BY_NAME (1)AUTOWIRE_BY_TYPE (2)AUTOWIRE_CONSTRUCTOR (3)
PS : 实际有五种,AUTOWIRE_AUTODETECT已过期,我们暂不讨论
默认情况下的注入模型
代码准备
创建配置类AppConfig
package com.test.model.config;import org.springframework.context.annotation.ComponentScan;ComponentScan(com.test.model)
public class AppConfig {}
创建一个普通bean
package com.test.model.component;import org.springframework.stereotype.Component;Component
public class MixComponent {}创建一个BeanFactoryPostProcessor(后面简称bfpp)
package com.test.model.bfpp;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component;Component
public class AutowireBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {AbstractBeanDefinition beanDefinition (AbstractBeanDefinition) registry.getBeanDefinition(mixComponent);int autowireMode beanDefinition.getAutowireMode();System.out.println(autowireMode);}Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}
创建启动类
package com.test.model;import com.test.model.config.AppConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Main {public static void main(String[] args) {AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(AppConfig.class);}
}
运行main方法,查看运行结果 结论 : 默认的注入模型是0 (AUTOWIRE_NO)
默认情况下的依赖注入
创建三个普通bean
Component
public class ComponentA {
}Component
public class ComponentB {
}Component
public class ComponentC {
}
依赖注入
package com.test.model.component;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;Component
public class MixComponent {Autowiredprivate ComponentA componentA;private ComponentB componentB;private ComponentC componentC;Autowiredpublic void setComponentB(ComponentB componentB) {this.componentB componentB;}public MixComponent() {}Autowiredpublic MixComponent(ComponentC componentC) {this.componentC componentC;}
}默认情况下的依赖注入的三种方式
属性注入setter注入构造器注入
运行main方法,查看运行结果 byName情况下的依赖注入
通过bfpp修改注入模型
package com.test.model.bfpp;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component;Component
public class AutowireBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {AbstractBeanDefinition beanDefinition (AbstractBeanDefinition) registry.getBeanDefinition(mixComponent);// 将注入模型改为byNamebeanDefinition.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);}Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}改造MixComponent
package com.test.model.component;import org.springframework.stereotype.Component;Component
public class MixComponent {// 没有Autowired注解private ComponentA componentA;// 没有Autowired注解private ComponentB componentB;// 没有Autowired注解private ComponentC componentC;public void setComponentA(ComponentA componentA) {this.componentA componentA;}public void setComponentB(ComponentB componentB) {this.componentB componentB;}public void setComponentC(ComponentC componentC) {this.componentC componentC;}
}运行main方法,查看运行结果 源码解析
AbstractAutowireCapableBeanFactory#populateBean
AbstractAutowireCapableBeanFactory#autowireByName
AbstractAutowireCapableBeanFactory#unsatisfiedNonSimpleProperties unsatisfiedNonSimpleProperties方法大概分为两个步骤
利用Spring的自省机制获取pds判断这个pd是否符合条件 判断pd是否存在writeMethod判断pd的propertyType是不是需要忽略的类pvs是否已存在相同name的值propertyType是不是普通类
我来解释一下pd需要满足的四个条件
条件1
package com.test.model.component;import org.springframework.stereotype.Component;Component
public class Demo1 {public Object getAbc() {return null;}public void setAbc(Object abc) {}public Object getXyz() {return null;}public void setXyz(Object xyz) {}
}不管我们是不是真实存在abc、xyz这样的属性只要类中存在setXxx或者getXxx这样的方法我们就认为类中存在一个名称为xxx的属性
PS : 我测试了一下,setXxx方法只能存在一个参数
条件2 比如bean实现了xxxAware接口,其相应的实现方法会被过滤掉
相关源码
AbstractApplicationContext#prepareBeanFactory
PS : 可能还有其他地方也添加了相关接口,debug的时候不止这几个
条件3
package com.test.model.bfpp;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component;Component
public class Demo1FactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {AbstractBeanDefinition b2 (AbstractBeanDefinition) registry.getBeanDefinition(demo1);b2.getPropertyValues().add(abc, new Object());}Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}我们可以手动给指定bean的属性设置值,那样就不会在Spring容器中查找符合条件的bean了。
条件4 Spring定义的普通类
byType情况下的依赖注入
byType和byName类似 主要就是根据参数类型从Spring中查找符合条件的bean,主要关注unsatisfiedNonSimpleProperties方法
测试发现一个有意思的情况,下方代码在byName的情况下会错,在byType的情况下会正确注入
package com.test.model.component;import org.springframework.stereotype.Component;Component
public class Demo2 {private ComponentC componentC;public void setComponentA(ComponentC componentC) {this.componentC componentC;}
}构造器注入
相关源码AbstractAutowireCapableBeanFactory#createBeanInstance 构造器注入并非只有注入模型是AUTOWIRE_CONSTRUCTOR才会执行构造器注入的逻辑,另外三个条件如果满足其一也会执行构造器注入,这里我用代码演示其他三种情况
具体细节可以看我之前写的博文Spring之推断构造方法https://blog.csdn.net/qq_38257958/article/details/134957631?spm1001.2014.3001.5501
ctors ! null的几种情况
package com.test.model.component;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;Component
public class Demo3 {/*** case1:有且仅有一个有参构造方法*/private ComponentA componentA;public Demo3(ComponentA componentA) {this.componentA componentA;}/*** case2:有且仅有一个Autowired(required true)标注的构造方法*/private ComponentB componentB;private ComponentC componentC;Autowired(required true)public Demo3(ComponentB componentB) {this.componentB componentB;}public Demo3(ComponentC componentC) {this.componentC componentC;}/*** case3:有多个Autowired(required false)标注的构造方法*/Autowired(required false)public Demo3(ComponentB componentB) {this.componentB componentB;}Autowired(required false)public Demo3(ComponentC componentC) {this.componentC componentC;}
}mbd.hasConstructorArgumentValues()
package com.test.model.component;import org.springframework.stereotype.Component;Component
public class Demo4 {private ComponentB componentB;private ComponentC componentC;public Demo4(ComponentB componentB) {this.componentB componentB;}public Demo4(ComponentC componentC) {this.componentC componentC;}
}package com.test.model.bfpp;import com.test.model.component.ComponentB;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component;Component
public class Demo4FactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {AbstractBeanDefinition beanDefinition (AbstractBeanDefinition) registry.getBeanDefinition(demo4);// 指定构造器Demo4(ComponentB componentB)beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0,new ComponentB());}Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}!ObjectUtils.isEmpty(args)
package com.test.model.component;import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;Component
Lazy
public class Demo5 {private ComponentB componentB;private ComponentC componentC;public Demo5(ComponentB componentB) {this.componentB componentB;}public Demo5(ComponentC componentC) {this.componentC componentC;}
}