@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());
- }
- }
(编辑:鞍山站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|