@构造器方式
例子
@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注解的原理