循环依赖构造器方式

文章目录

@构造器方式

例子

@Component
public class TestA {

    private TestB testB;

    public TestA(TestB testB) {
        this.testB = testB;
    }
}
@Component
public class TestB {

    private TestA testA;

    public TestB(TestA testA) {
        this.testA = testA;
    }
}
  • TestA开始,当执行到AbstractAutowireCapableBeanFactory createBean–》createBeanInstance–〉判断是否是构造器注入【AUTOWIRE_CONSTRUCTOR参见AutowireCapableBeanFactory类】

  • ConstructorResolver 构造器注入,当执行到如下代码时候,会将参数实例化,就造成了A使用B,需要实例化B,B使用A需要实例化A的情况,为什么Autowire不会出现呢?因为Autowire反射不需要依赖参数,反射后生成Bean放入第三级缓存,而构造函数是反射实例化过程中出现依赖,还没有实例化的Bean放入三级缓存

    argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
          getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
    

    获取构造器

    protected Constructor<?> getUserDeclaredConstructor(Constructor<?> constructor) {
       Class<?> declaringClass = constructor.getDeclaringClass();
       Class<?> userClass = ClassUtils.getUserClass(declaringClass);
       if (userClass != declaringClass) {
          try {
             return userClass.getDeclaredConstructor(constructor.getParameterTypes());
          }
          catch (NoSuchMethodException ex) {
             // No equivalent constructor on user class (superclass)...
             // Let's proceed with the given constructor as we usually would.
          }
       }
       return constructor;
    }
    

    创建参数createArgumentArray,之后调用DefaultListableBeanFactory resolveDependency()方法,然后调用ContextAnnotationAutowireCandidateResolver getLazyResolutionProxyIfNecessary()方法,Lazy判断,如果懒加载,则使用buildLazyResolutionProxy进行代理,

    public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
    		return (isLazy(descriptor) ? buildLazyResolutionProxy(descriptor, beanName) : null);
    	}
    protected boolean isLazy(DependencyDescriptor descriptor) {
       for (Annotation ann : descriptor.getAnnotations()) {
          Lazy lazy = AnnotationUtils.getAnnotation(ann, Lazy.class);
          if (lazy != null && lazy.value()) {
             return true;
          }
       }
       MethodParameter methodParam = descriptor.getMethodParameter();
       if (methodParam != null) {
          Method method = methodParam.getMethod();
          if (method == null || void.class == method.getReturnType()) {
             Lazy lazy = AnnotationUtils.getAnnotation(methodParam.getAnnotatedElement(), Lazy.class);
             if (lazy != null && lazy.value()) {
                return true;
             }
          }
       }
       return false;
    }
    protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {
    		Assert.state(getBeanFactory() instanceof DefaultListableBeanFactory,
    				"BeanFactory needs to be a DefaultListableBeanFactory");
    		final DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) getBeanFactory();
    		TargetSource ts = new TargetSource() {
    			@Override
    			public Class<?> getTargetClass() {
    				return descriptor.getDependencyType();
    			}
    			@Override
    			public boolean isStatic() {
    				return false;
    			}
    			@Override
    			public Object getTarget() {
    				Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null);
    				if (target == null) {
    					Class<?> type = getTargetClass();
    					if (Map.class == type) {
    						return Collections.emptyMap();
    					}
    					else if (List.class == type) {
    						return Collections.emptyList();
    					}
    					else if (Set.class == type || Collection.class == type) {
    						return Collections.emptySet();
    					}
    					throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),
    							"Optional dependency not present for lazy injection point");
    				}
    				return target;
    			}
    			@Override
    			public void releaseTarget(Object target) {
    			}
    		};
    		ProxyFactory pf = new ProxyFactory();
    		pf.setTargetSource(ts);
    		Class<?> dependencyType = descriptor.getDependencyType();
    		if (dependencyType.isInterface()) {
    			pf.addInterface(dependencyType);
    		}
    		return pf.getProxy(beanFactory.getBeanClassLoader());
    	}
    

为什么Autowire不会出现呢

因为Autowire反射不需要依赖参数,反射后生成Bean放入第三级缓存,而构造函数是反射实例化过程中出现依赖,还没有实例化的Bean放入三级缓存

如何解决?

加入@Lazy生成代理

代码如下ContextAnnotationAutowireCandidateResolver:

public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
   return (isLazy(descriptor) ? buildLazyResolutionProxy(descriptor, beanName) : null);
}
protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {
		BeanFactory beanFactory = getBeanFactory();
		Assert.state(beanFactory instanceof DefaultListableBeanFactory,
				"BeanFactory needs to be a DefaultListableBeanFactory");
		final DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory;

		TargetSource ts = new TargetSource() {
			@Override
			public Class<?> getTargetClass() {
				return descriptor.getDependencyType();
			}
			@Override
			public boolean isStatic() {
				return false;
			}
			@Override
			public Object getTarget() {
				Set<String> autowiredBeanNames = (beanName != null ? new LinkedHashSet<>(1) : null);
				Object target = dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null);
				if (target == null) {
					Class<?> type = getTargetClass();
					if (Map.class == type) {
						return Collections.emptyMap();
					}
					else if (List.class == type) {
						return Collections.emptyList();
					}
					else if (Set.class == type || Collection.class == type) {
						return Collections.emptySet();
					}
					throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),
							"Optional dependency not present for lazy injection point");
				}
				if (autowiredBeanNames != null) {
					for (String autowiredBeanName : autowiredBeanNames) {
						if (dlbf.containsBean(autowiredBeanName)) {
							dlbf.registerDependentBean(autowiredBeanName, beanName);
						}
					}
				}
				return target;
			}
			@Override
			public void releaseTarget(Object target) {
			}
		};

		ProxyFactory pf = new ProxyFactory();
		pf.setTargetSource(ts);
		Class<?> dependencyType = descriptor.getDependencyType();
		if (dependencyType.isInterface()) {
			pf.addInterface(dependencyType);
		}
		return pf.getProxy(dlbf.getBeanClassLoader());
	}

ContextAnnotationAutowireCandidateResolver
官方把这个类描述为:策略接口的完整实现。它不仅仅支持上面所有描述的功能,还支持@Lazy懒处理~~~(注意此处懒处理(延迟处理),不是懒加载~)

@Lazy一般含义是懒加载,它只会作用于BeanDefinition.setLazyInit()。而此处给它增加了一个能力:延迟处理(代理处理)
它很好的用到了TargetSource这个接口,结合动态代理来支持到了@Lazy注解。
标注有@Lazy注解完成注入的时候,最终注入只是一个此处临时生成的代理对象,只有在真正执行目标方法的时候才会去容器内拿到真是的bean实例来执行目标方法,每次执行目标方法的时候都会去执行TargetSource.getTarget()方法。

参考:Spring实例化之AutowireCandidateResolver深度分析,解析@Lazy、@Qualifier注解的原理

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值