ContextAnnotationAutowireCandidateResolver
官方把这个类描述为:策略接口的完整实现。它不仅仅支持上面所有描述的功能,还支持@Lazy懒处理~~~(注意此处懒处理(延迟处理),不是懒加载~)
@Lazy一般含义是懒加载,它只会作用于BeanDefinition.setLazyInit()。而此处给它增加了一个能力:延迟处理(代理处理)
// @since 4.0 出现得挺晚,它支持到了@Lazy 是功能最全的AutowireCandidateResolver public class ContextAnnotationAutowireCandidateResolver extends QualifierAnnotationAutowireCandidateResolver { // 这是此类本身唯一做的事,此处精析 // 返回该 lazy proxy 表示延迟初始化,实现过程是查看在 @Autowired 注解处是否使用了 @Lazy = true 注解 @Override @Nullable public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) { // 如果isLazy=true 那就返回一个代理,否则返回null // 相当于若标注了@Lazy注解,就会返回一个代理(当然@Lazy注解的value值不能是false) return (isLazy(descriptor) ? buildLazyResolutionProxy(descriptor, beanName) : null); } // 这个比较简单,@Lazy注解标注了就行(value属性默认值是true) // @Lazy支持标注在属性上和方法入参上~~~ 这里都会解析 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"); // 这里毫不客气的使用了面向实现类编程,使用了DefaultListableBeanFactory.doResolveDependency()方法~~~ final DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) getBeanFactory(); //TargetSource 是它实现懒加载的核心原因,在AOP那一章节了重点提到过这个接口,此处不再叙述 // 它有很多的著名实现如HotSwappableTargetSource、SingletonTargetSource、LazyInitTargetSource、 //SimpleBeanTargetSource、ThreadLocalTargetSource、PrototypeTargetSource等等非常多 // 此处因为只需要自己用,所以采用匿名内部类的方式实现~~~ 此处最重要是看getTarget方法,它在被使用的时候(也就是代理对象真正使用的时候执行~~~) TargetSource ts = new TargetSource() { @Override public Class<?> getTargetClass() { return descriptor.getDependencyType(); } @Override public boolean isStatic() { return false; } // getTarget是调用代理方法的时候会调用的,所以执行每个代理方法都会执行此方法,这也是为何doResolveDependency // 我个人认为它在效率上,是存在一定的问题的~~~所以此处建议尽量少用@Lazy~~~ //不过效率上应该还好,对比http、序列化反序列化处理,简直不值一提 所以还是无所谓 用吧 @Override public Object getTarget() { Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null); if (target == null) { Class<?> type = getTargetClass(); // 对多值注入的空值的友好处理(不要用null) 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 给ts生成一个代理 // 由此可见最终生成的代理对象的目标对象其实是TargetSource,而TargetSource的目标才是我们业务的对象 ProxyFactory pf = new ProxyFactory(); pf.setTargetSource(ts); Class<?> dependencyType = descriptor.getDependencyType(); // 如果注入的语句是这么写的private AInterface a; 那这类就是借口 值是true // 把这个接口类型也得放进去(不然这个代理都不属于这个类型,反射set的时候岂不直接报错了吗????) if (dependencyType.isInterface()) { pf.addInterface(dependencyType); } return pf.getProxy(beanFactory.getBeanClassLoader()); } }
它很好的用到了TargetSource这个接口,结合动态代理来支持到了@Lazy注解。
标注有@Lazy注解完成注入的时候,最终注入只是一个此处临时生成的代理对象,只有在真正执行目标方法的时候才会去容器内拿到真是的bean实例来执行目标方法。
特别注意:此代理对象非彼代理对象,这个一定一定一定要区分开来~
通过@Lazy注解能够解决很多情况下的循环依赖问题,它的基本思想是先'随便'给你创建一个代理对象先放着,等你真正执行方法的时候再实际去容器内找出目标实例执行~
我们要明白这种解决问题的思路带来的好处是能够解决很多场景下的循环依赖问题,但是要知道它每次执行目标方法的时候都会去执行TargetSource.getTarget()方法,所以需要做好缓存,避免对执行效率的影响(实测执行效率上的影响可以忽略不计)
ContextAnnotationAutowireCandidateResolver这个处理器才是被Bean工厂最终最终使用的,因为它的功能是最全的~
回顾一下,注册进Bean工厂的参考代码处:
public abstract class AnnotationConfigUtils { ... public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) { DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null) { // 设置默认的排序器 支持@Order等 if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } // 设置依赖注入的候选处理器 // 可以看到只要不是ContextAnnotationAutowireCandidateResolver类型 直接升级为最强类型 if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } ... // ====下面是大家熟悉的注册默认6大后置处理器:==== // 1.ConfigurationClassPostProcessor // 2.AutowiredAnnotationBeanPostProcessor // 3.CommonAnnotationBeanPostProcessor // 4.Jpa的PersistenceAnnotationProcessor(没导包就不会注册) // 5.EventListenerMethodProcessor // 6.DefaultEventListenerFactory } ... }
此段代码执行还是非常早的,在容器的刷新时的ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();这一步就完成了~
最后,把这个四个哥们 从上至下 简单总结如下:
- SimpleAutowireCandidateResolver 相当于一个简单的适配器
- GenericTypeAwareAutowireCandidateResolver 判断泛型是否匹配,支持泛型依赖注入(From Spring4.0)
- QualifierAnnotationAutowireCandidateResolver 处理 @Qualifier 和 @Value 注解
- ContextAnnotationAutowireCandidateResolver 处理 @Lazy 注解,重写了 getLazyResolutionProxyIfNecessary 方法。