zoukankan      html  css  js  c++  java
  • Spring杂谈 | Spring中的AutowireCandidateResolver

    接口定义

    用于推断一个特定的beanDefinition是否能作为指定依赖的候选者的策略接口

    public interface AutowireCandidateResolver {
    	// 默认情况下直接根据bd中的定义返回,如果没有进行特殊配置的话为true
    	default boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
    		return bdHolder.getBeanDefinition().isAutowireCandidate();
    	}
    	
        // 指定的依赖是否是必要的
    	default boolean isRequired(DependencyDescriptor descriptor) {
    		return descriptor.isRequired();
    	}
    	
        // QualifierAnnotationAutowireCandidateResolver做了实现,判断是否有@Qualifier注解
        // 一共有两种注解:
        // 1.Spring内置的@Qualifier注解,org.springframework.beans.factory.annotation.Qualifier
        // 2.添加了JSR-330相关依赖,javax.inject.Qualifier注解
        // 默认情况下返回false
    	default boolean hasQualifier(DependencyDescriptor descriptor) {
    		return false;
    	}
    	
        // QualifierAnnotationAutowireCandidateResolver做了实现
        // 获取一个该依赖一个建议的值
    	@Nullable
    	default Object getSuggestedValue(DependencyDescriptor descriptor) {
    		return null;
    	}
    	
        // 对某个依赖我们想要延迟注入,但是在创建Bean的过程中这个依赖又是必须的
        // 通过下面这个方法就能为延迟注入的依赖先生成一个代理注入到bean中
    	@Nullable
    	default Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
    		return null;
    	}
    
    }
    

    继承关系

    在这里插入图片描述

    可以看到继承关系都是单层的,我们就一个一个往下看

    SimpleAutowireCandidateResolver

    相比于接口没有什么区别,实现也就是父接口中的默认实现,一般也不会使用这个类

    public class SimpleAutowireCandidateResolver implements AutowireCandidateResolver {
    
    	@Override
    	public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
    		return bdHolder.getBeanDefinition().isAutowireCandidate();
    	}
    
    	@Override
    	public boolean isRequired(DependencyDescriptor descriptor) {
    		return descriptor.isRequired();
    	}
    
    	@Override
    	@Nullable
    	public Object getSuggestedValue(DependencyDescriptor descriptor) {
    		return null;
    	}
    
    	@Override
    	@Nullable
    	public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
    		return null;
    	}
    
    }
    
    

    GenericTypeAwareAutowireCandidateResolver

    额外增加了对泛型的处理能力

    public class GenericTypeAwareAutowireCandidateResolver extends SimpleAutowireCandidateResolver
    		implements BeanFactoryAware {
    
    	@Nullable
    	private BeanFactory beanFactory;
    
    
    	@Override
    	public void setBeanFactory(BeanFactory beanFactory) {
    		this.beanFactory = beanFactory;
    	}
    
    	@Nullable
    	protected final BeanFactory getBeanFactory() {
    		return this.beanFactory;
    	}
    
    
    	@Override
    	public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
    		if (!super.isAutowireCandidate(bdHolder, descriptor)) {
    			// 如果bd中已经配置了这个bean不做为依赖进行注入的话,直接返回false
    			return false;
    		}
            // 检查泛型是否匹配
    		return checkGenericTypeMatch(bdHolder, descriptor);
    	}
    
    }
    

    QualifierAnnotationAutowireCandidateResolver

    增加了对@Qualifier注解以及@Value注解的处理能力

    public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwareAutowireCandidateResolver {
    
    	private final Set<Class<? extends Annotation>> qualifierTypes = new LinkedHashSet<>(2);
    	// @Value注解
    	private Class<? extends Annotation> valueAnnotationType = Value.class;
    	
        // @Qualifier注解
    	@SuppressWarnings("unchecked")
    	public QualifierAnnotationAutowireCandidateResolver() {
    		this.qualifierTypes.add(Qualifier.class);
    		try {
    			this.qualifierTypes.add((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Qualifier",
    							QualifierAnnotationAutowireCandidateResolver.class.getClassLoader()));
    		}
    		catch (ClassNotFoundException ex) {
    			// JSR-330 API not available - simply skip.
    		}
    	}
    
    	// .......
    
    	@Override
    	public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
            // 类型上已经匹配了
    		boolean match = super.isAutowireCandidate(bdHolder, descriptor);
    		if (match) {
                // 还需要判断是否满足@Qualifier注解的要求
    			match = checkQualifiers(bdHolder, descriptor.getAnnotations());
    			if (match) {
    				MethodParameter methodParam = descriptor.getMethodParameter();
    				if (methodParam != null) {
    					Method method = methodParam.getMethod();
    					if (method == null || void.class == method.getReturnType()) {
    						match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations());
    					}
    				}
    			}
    		}
    		return match;
    	}
    
    	// .....
    	
        // 是否是@Qualifier注解
    	protected boolean isQualifier(Class<? extends Annotation> annotationType) {
    		for (Class<? extends Annotation> qualifierType : this.qualifierTypes) {
    			if (annotationType.equals(qualifierType) || annotationType.isAnnotationPresent(qualifierType)) {
    				return true;
    			}
    		}
    		return false;
    	}
    	
    	@Override
    	@Nullable
    	public Object getSuggestedValue(DependencyDescriptor descriptor) {
    		Object value = findValue(descriptor.getAnnotations());
    		if (value == null) {
    			MethodParameter methodParam = descriptor.getMethodParameter();
    			if (methodParam != null) {
    				value = findValue(methodParam.getMethodAnnotations());
    			}
    		}
    		return value;
    	}
    	
        
        // 查找@Value注解
    	@Nullable
    	protected Object findValue(Annotation[] annotationsToSearch) {
    		if (annotationsToSearch.length > 0) {   
    			AnnotationAttributes attr = AnnotatedElementUtils.getMergedAnnotationAttributes(
    					AnnotatedElementUtils.forAnnotations(annotationsToSearch), this.valueAnnotationType);
    			if (attr != null) {
    				return extractValue(attr);
    			}
    		}
    		return null;
    	}
    	
        // 获取@Value注解中的值
    	protected Object extractValue(AnnotationAttributes attr) {
    		Object value = attr.get(AnnotationUtils.VALUE);
    		if (value == null) {
    			throw new IllegalStateException("Value annotation must have a value attribute");
    		}
    		return value;
    	}
    
    }
    

    ContextAnnotationAutowireCandidateResolver

    这个类是最底层的子类,集成了所有的方法,并且额外提供了对依赖进行延迟处理的能力

    public class ContextAnnotationAutowireCandidateResolver extends QualifierAnnotationAutowireCandidateResolver {
    	
        // 如果依赖需要进行延迟处理,那么构建一个代理对象先注入到bean中,不会直接去创建依赖对象
    	@Override
    	@Nullable
    	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) {
    		final DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) getBeanFactory();
            
            // 创建了一个TargetSource
    		TargetSource ts = new TargetSource() {
    			@Override
    			public Class<?> getTargetClass() {
    				return descriptor.getDependencyType();
    			}
    			@Override
    			public boolean isStatic() {
    				return false;
    			}
                // target是我们实际想要使用的对象,如果不进行延迟处理,那么注入到bean中的应该就是这个对象
                // 但是因为要进行延迟注入依赖,所有会向外暴露一个TargetSource,这个TargetSource的目标为实际想要使用的对象,生成代理时会基于TargetSource进行生成。在运行期间(完成注入后)我们使用这个延迟处理的依赖时实际调用的会是target中的方法。
    			@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,给TargetSource生成一个代理
    		ProxyFactory pf = new ProxyFactory();
    		pf.setTargetSource(ts);
    		Class<?> dependencyType = descriptor.getDependencyType();
            // 如果依赖的类型是一个接口,需要让代理类也实现这个接口
    		if (dependencyType.isInterface()) {
    			pf.addInterface(dependencyType);
    		}
            // 生成代理
    		return pf.getProxy(beanFactory.getBeanClassLoader());
    	}
    
    }
    

    总结

    • SimpleAutowireCandidateResolver:单纯的将接口变成了可实例化的类,方法实现跟接口保持一致
    • GenericTypeAwareAutowireCandidateResolver: 判断泛型是否匹配,支持泛型依赖注入(From Spring4.0)
    • QualifierAnnotationAutowireCandidateResolver :处理 @Qualifier 和 @Value 注解
    • ContextAnnotationAutowireCandidateResolver :处理依赖级别的 @Lazy 注解,重写了getLazyResolutionProxyIfNecessary 方法。
  • 相关阅读:
    win7下安装配置tomcat,java运行环境
    Ubuntu 12.10安装配置JDK7环境
    全面介绍Linux终端命令
    Ubuntu 配置 Tomcat
    Linux手动导入导出mysql数据库
    navicat数据库管理软件(支持mysql,oracle,sqlserver,sqlite,postgreSQL)
    信号量(semaphore)和互斥量(mutex)
    最新版fcitx 4.1.2源码编译安装(ubuntu 10.04)
    Groovy动态语言简介
    读书笔记:《java脚本编程:语言、框架与模式》(2)jvm内部的脚本语言
  • 原文地址:https://www.cnblogs.com/daimzh/p/12854379.html
Copyright © 2011-2022 走看看