深度分析Spring中的构造器注入
阅读本文大概需要 13 分钟。
来自:blog.csdn.net/z69183787/article/details/108902510
1. 示例
public class ConstructorAutowiredTest {
private User user;
private Role role;
public ConstructorAutowiredTest() {
}
public ConstructorAutowiredTest(User user) {
this.user = user;
}
public ConstructorAutowiredTest(User user, Role role) {
this.user = user;
this.role = role;
}
public void test(){
System.out.println("user: "+user);
System.out.println("role: "+role);
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd ">
<context:annotation-config/>
<bean class="com.mytest.demo.model.Role" id="role">
<property name="name" value="testRole"/>
<property name="id" value="2"/>
bean>
<bean class="com.mytest.demo.model.User" id="user">
<property name="id" value="1"/>
<property name="name" value="testUser"/>
bean>
<bean class="com.mytest.demo.autowired.ConstructorAutowiredTest" id="test"/>
beans>
此自定义标签开启(关于自定义标签,在本人往期的Spring系列中有详细介绍),具体作用后面再作分析。public class TestBeanAutowiredConstructor {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
context.setConfigLocation("context.xml");
context.refresh();
ConstructorAutowiredTest test = (ConstructorAutowiredTest) context.getBean("test");
test.test();
}
}
// public ConstructorAutowiredTest() {
// }
public ConstructorAutowiredTest(User user) {
this.user = user;
}
// public ConstructorAutowiredTest(User user, Role role) {
// this.user = user;
// this.role = role;
// }
public ConstructorAutowiredTest() {
}
public ConstructorAutowiredTest(User user) {
this.user = user;
}
@Autowired
public ConstructorAutowiredTest(User user, Role role) {
this.user = user;
this.role = role;
}
public ConstructorAutowiredTest() {
}
@Autowired(required = false)
public ConstructorAutowiredTest(User user) {
this.user = user;
}
@Autowired(required = false)
public ConstructorAutowiredTest(User user, Role role) {
this.user = user;
this.role = role;
}
为什么写三个构造器(含有无参构造器),并且没有@Autowired注解,Spring总是使用无参构造器实例化Bean? 为什么注释掉两个构造器,留下一个有参构造器,并且没有@Autowired注解,Spring将会使用构造器注入Bean的方式初始化Bean? 为什么写三个构造器,并且在其中一个构造器上打上**@Autowired注解,就可以正常注入构造器?并且两个@Autowired注解就会报错**,一定需要在所有@Autowired中的required都加上false即可正常初始化等等?
2. 依赖注入伊始
xmlns:context="http://www.springframework.org/schema/context"
http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
public void init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
public BeanDefinition parse(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);
// Obtain bean definitions for all relevant BeanPostProcessors.
//定义一系列BeanDefinition,放入一个Set集合中
SetprocessorDefinitions =
AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);
//注册一系列BeanDefinition,此处略过..
}
public static Set registerAnnotationConfigProcessors( {
BeanDefinitionRegistry registry, @Nullable Object source)
//将registry对象转型成beanFactroy
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
SetbeanDefs = new LinkedHashSet<>(8);
//判断容器中是否已经存在名为AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME的Bean
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//若是不存在,创建一个
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//中途还添加了一系列BeanDefinition,不是本文讨论范围,略过...
return beanDefs;
}
3. 初始化Bean
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
//略过一些与本文无关的其他实例化的方式的代码...
// Candidate constructors for autowiring?
// 查找是否存在候选的自动注入构造器
Constructor>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//使用注入的方式调用构造器实例化
return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
//使用无参构造器实例化(利用反射newInstance)
return instantiateBean(beanName, mbd);
}
protected Constructor>[] determineConstructorsFromBeanPostProcessors(@Nullable Class> beanClass, String beanName)
throws BeansException {
//容器中若存在InstantiationAwareBeanPostProcessors
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
//遍历此BeanPostProcessors
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//只使用SmartInstantiationAwareBeanPostProcessor类型
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
Constructor>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
}
return null;
}
public Constructor>[] determineCandidateConstructors(Class> beanClass, final String beanName)
throws BeanCreationException {
//略..
// Quick check on the concurrent map first, with minimal locking.
//先查找缓存
Constructor>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
//若是缓存中没有
if (candidateConstructors == null) {
// Fully synchronized resolution now...
//同步此方法
synchronized (this.candidateConstructorsCache) {
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
//双重判断,避免多线程并发问题
if (candidateConstructors == null) {
Constructor>[] rawCandidates;
try {
//获取此Bean的所有构造器
rawCandidates = beanClass.getDeclaredConstructors();
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
//最终适用的构造器集合
List> candidates = new ArrayList<>(rawCandidates.length);
//存放依赖注入的required=true的构造器
Constructor> requiredConstructor = null;
//存放默认构造器
Constructor> defaultConstructor = null;
Constructor> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
int nonSyntheticConstructors = 0;
for (Constructor> candidate : rawCandidates) {
if (!candidate.isSynthetic()) {
nonSyntheticConstructors++;
}
else if (primaryConstructor != null) {
continue;
}
//查找当前构造器上的注解
AnnotationAttributes ann = findAutowiredAnnotation(candidate);
//若没有注解
if (ann == null) {
Class> userClass = ClassUtils.getUserClass(beanClass);
if (userClass != beanClass) {
try {
Constructor> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
//若有注解
if (ann != null) {
//已经存在一个required=true的构造器了,抛出异常
if (requiredConstructor != null) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
//判断此注解上的required属性
boolean required = determineRequiredStatus(ann);
//若为true
if (required) {
if (!candidates.isEmpty()) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructors: " + candidates +
". Found constructor with 'required' Autowired annotation: " +
candidate);
}
//将当前构造器加入requiredConstructor集合
requiredConstructor = candidate;
}
//加入适用的构造器集合中
candidates.add(candidate);
}
//如果该构造函数上没有注解,再判断构造函数上的参数个数是否为0
else if (candidate.getParameterCount() == 0) {
//如果没有参数,加入defaultConstructor集合
defaultConstructor = candidate;
}
}
//适用的构造器集合若不为空
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
//若没有required=true的构造器
if (requiredConstructor == null) {
if (defaultConstructor != null) {
//将defaultConstructor集合的构造器加入适用构造器集合
candidates.add(defaultConstructor);
}
else if (candidates.size() == 1 && logger.isInfoEnabled()) {
logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
"': single autowire-marked constructor flagged as optional - " +
"this constructor is effectively required since there is no " +
"default constructor to fall back to: " + candidates.get(0));
}
}
//将适用构造器集合赋值给将要返回的构造器集合
candidateConstructors = candidates.toArray(new Constructor>[0]);
}
//如果适用的构造器集合为空,且Bean只有一个构造器并且此构造器参数数量大于0
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
//就使用此构造器来初始化
candidateConstructors = new Constructor>[] {rawCandidates[0]};
}
//如果构造器有两个,且默认构造器不为空
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
//使用默认构造器返回
candidateConstructors = new Constructor>[] {primaryConstructor, defaultConstructor};
}
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor>[] {primaryConstructor};
}
else {
//上述都不符合的话,只能返回一个空集合了
candidateConstructors = new Constructor>[0];
}
//放入缓存,方便下一次调用
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
//返回candidateConstructors集合,若为空集合返回null
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
无参构造器将直接加入defaultConstructor集合中。 在构造器数量只有一个且有参数时,此唯一有参构造器将加入candidateConstructors集合中。 在构造器数量有两个的时候,并且存在无参构造器,将defaultConstructor(第一条的无参构造器)放入candidateConstructors集合中。 在构造器数量大于两个,并且存在无参构造器的情况下,将返回一个空的candidateConstructors集合,也就是没有找到构造器。
判断required属性: true:先判断requiredConstructor集合是否为空,若不为空则代表之前已经有一个required=true的构造器了,两个true将抛出异常,再判断candidates集合是否为空,若不为空则表示之前已经有一个打了注解的构造器,此时required又是true,抛出异常。若两者都为空将放入requiredConstructor集合中,再放入candidates集合中。 false:直接放入candidates集合中。 判断requiredConstructor集合是否为空(是否存在required=true的构造器),若没有,将默认构造器也放入candidates集合中。 最后将上述candidates赋值给最终返回的candidateConstructors集合。
4.总结
也就是说,若使用@Autowired注解进行构造器注入,required属性都设置为false的话,将避免无Bean注入的异常,使用无参构造器正常实例化。若两个参数都是Bean,则就直接使用两个参数的构造器进行实例化并获取对应Bean注入构造器。
推荐阅读:
字符串拼接还在用StringBuilder?快试试Java8中的StringJoiner吧,真香!
内容包含Java基础、JavaWeb、MySQL性能优化、JVM、锁、百万并发、消息队列、高性能缓存、反射、Spring全家桶原理、微服务、Zookeeper、数据结构、限流熔断降级......等技术栈!
⬇戳阅读原文领取! 朕已阅
评论