SpringIOC(五)byType、@Autowire⾃动装配源码分析——根据类型属性注⼊⽬录
本⽂主要分析byType类型和@Autowire注解的⾃动装配过程
两者是有相似之处的:都是根据类型选取符合条件的Bean,然后筛选。
不同的是,⽬标类型有多个Bean符合条件时,byType不会对属性名进⾏判断直接抛出错误,⽽@Autowire会再按照属性名筛选。
byType源码分析
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs){
TypeConverter converter =getCustomTypeConverter();
if(converter == null){
converter = bw;
}
Set<String> autowiredBeanNames =new LinkedHashSet<String>(4);
String[] propertyNames =unsatisfiedNonSimpleProperties(mbd, bw);
for(String propertyName : propertyNames){
try{
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
if(Object.class!= pd.getPropertyType()){
MethodParameter methodParam = WriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager =!PriorityOrdered.class.WrappedClass());
DependencyDescriptor desc =new AutowireByTypeDependencyDescriptor(methodParam, eager);
Object autowiredArgument =resolveDependency(desc, beanName, autowiredBeanNames, converter);
if(autowiredArgument != null){
pvs.add(propertyName, autowiredArgument);
}
for(String autowiredBeanName : autowiredBeanNames){
registerDependentBean(autowiredBeanName, beanName);
if(logger.isDebugEnabled()){
logger.debug("Autowiring by type from bean name '"+ beanName +"' via property '"+
propertyName +"' to bean named '"+ autowiredBeanName +"'");
}
}
autowiredBeanNames.clear();
}
}
catch(BeansException ex){
throw new ResourceDescription(), beanName, propertyName, ex);
}
}
}
根据类型⾃动装配:
⾸先得到 所有需要装配的⾮简单属性 ,(不是字符串等简单类型)也就是Bean类型的属性,并返回
检查此属性的set⽅法,存在的时候才可⾃动装配
创建⼀个AutowireByType类型的依赖描述符
resolveDependency:解析依赖关系 ,返回依赖的Bean实例,这个⽅法在本篇最后分析。
保存返回的依赖Bean实例:pvs.add(propertyName, autowiredArgument)
记录依赖关系
(最后将在applyPropertyValues中实现pvs中的属性注⼊)
注意,其中有⼀⾏DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
/**
* Special DependencyDescriptor variant for Spring's good old autowire="byType" mode.
* Always optional; never considering the parameter name for choosing a primary candidate.
*/
@SuppressWarnings("serial")
private static class AutowireByTypeDependencyDescriptor extends DependencyDescriptor {
public AutowireByTypeDependencyDescriptor(MethodParameter methodParameter,boolean eager){
super(methodParameter,false, eager);
}
@Override
public String getDependencyName(){
return null;
}
}
表⽰byType形式的依赖描述符有⼀种特殊的表⽰: 在选择主要候选对象时从不考虑参数名称!
这句话什么意思呢,就是使⽤byType形式的⾃动装配,当此Type的Bean有多个时,将会直接抛出错误,⽽不是再根据参数的Name去匹配第⼆遍。
主要是与@Autowired形式的属性注⼊的特点形成对⽐,具体分析如下。
@Autowired注解⾃动装配过程
@Autowired 可以对成员变量、⽅法以及构造函数进⾏注释。我们在⽇常开发的过程中主要使⽤的是对成员变量的⾃动装配,即先使⽤默认构造器创建实例之后,再通过注解使⽤setter注⼊属性。
使⽤⽅式
@Component
public class Cat {
public String toString(){
return"miao";
}
}
@Component
public class Animal {
@Autowired
private Cat cat;
public Cat getCat(){
return this.cat;
}
public void setCat(Cat cat){
this.cat = cat;
}
}
public class MainTest {
public static void main(String[] args){
ApplicationContext ac =new ClassPathXmlApplicationContext("l");
Animal animal = ac.getBean(Animal.class);
System.out.Cat().toString());
}
}
<context:component-scan base-package="*"/>
抛出问题
由上⽂可知,实现@Autowire类型属性注⼊的后处理器是AutowiredAnnotationBeanPostProcessor,该接⼝继承了InstantiationAwareBeanPostProcessor,实现了postProcessPropertyValues⽅法。
AutowiredAnnotationBeanPostProcessor何时被注册?
当解析xml配置⽂件的<context:component-scan />标签时,会将AutowiredAnnotationBeanPostProcessor注册到⼯⼚。
AutowiredAnnotationBeanPostProcessor何时被调⽤?
对于@Autowire注解的属性注⼊,在整个Bean的属性填充中分为两个步骤:
1. 注解的解析
在的第2步:当创建完初始实例之后 ,会进⾏applyMergedBeanDefinitionPostProcessors:获取全部的
MergedBeanDefinitionPostProcessor,然后遍历执⾏其postProcessMergedBeanDefinition⽅法。这个⽅法的意义为对MergedBeanDefinition进⾏修改,即对 bean定义 进⾏后期处理。
AutowiredAnnotationBeanPostProcessor继承了MergedBeanDefinitionPostProcessor,在
AutowiredAnnotationBeanPostProcessor中的实现即为:对@Autowire注解的Field及Method进⾏解析,并放⼊
injectionMetadataCache缓存 中。
2. 属性的注⼊
在中的第4-3步:InstantiationAwareBeanPostProcessor.postProcessPropertyValues。
AutowiredAnnotationBeanPostProcessor继承了InstantiationAwareBeanPostProcessor,在
AutowiredAnnotationBeanPostProcessor中的实现即为:到被Autowired注解的属性(从injectionMetadataCache缓存中获取),进⾏属性注⼊。
@Autowired源码分析
第1步:MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition源码
分析
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName){ if(beanType != null){
InjectionMetadata metadata =findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
}
⽅法包括了:
1. findAutowiringMetadata在Bean中到所有@Autowire注解的元数据
2. checkConfigMembers检查元数据中的信息
第1-1步:findAutowiringMetadata在Bean中到所有@Autowire注解的元数据
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs){
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey =(StringUtils.hasLength(beanName)? beanName : Name());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata =(cacheKey);
dsRefresh(metadata, clazz)){
synchronized(this.injectionMetadataCache){
metadata =(cacheKey);
dsRefresh(metadata, clazz)){
if(metadata != null){
metadata.clear(pvs);
}
try{
metadata =buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
catch(NoClassDefFoundError err){
throw new IllegalStateException("Failed to introspect bean class ["+ Name()+
"] for autowiring metadata: could not find class that it depends on", err);
}
}
}
}
return metadata;
}
⽬标元数据使⽤缓存存储,关键的解析注解⽣成元数据的⽅法是buildAutowiringMetadata:
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz){
LinkedList<InjectionMetadata.InjectedElement> elements =new LinkedList<InjectionMetadata.InjectedElement>();
Class<?> targetClass = clazz;
do{
final LinkedList<InjectionMetadata.InjectedElement> currElements =
new LinkedList<InjectionMetadata.InjectedElement>();
ReflectionUtils.doWithLocalFields(targetClass,new ReflectionUtils.FieldCallback(){
@Override
public void doWith(Field field)throws IllegalArgumentException, IllegalAccessException {
AnnotationAttributes ann =findAutowiredAnnotation(field);
resource和autowired注解的区别if(ann != null){
if(Modifier.Modifiers())){
if(logger.isWarnEnabled()){
logger.warn("Autowired annotation is not supported on static fields: "+ field);
}
return;
}
boolean required =determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
}
});
ReflectionUtils.doWithLocalMethods(targetClass,new ReflectionUtils.MethodCallback(){
@Override
public void doWith(Method method)throws IllegalArgumentException, IllegalAccessException {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if(!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)){
return;
}
AnnotationAttributes ann =findAutowiredAnnotation(bridgedMethod);
if(ann != null && method.MostSpecificMethod(method, clazz))){
if(Modifier.Modifiers())){
if(logger.isWarnEnabled()){
logger.warn("Autowired annotation is not supported on static methods: "+ method);
}
return;
}
ParameterTypes().length ==0){
if(logger.isWarnEnabled()){
logger.warn("Autowired annotation should be used on methods with parameters: "+ method);
}
}
boolean required =determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
}
});
elements.addAll(0, currElements);
targetClass = Superclass();
}
while(targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
关注上半部分,doWithLocalFields,到Bean中带有注解的属性。其中的findAutowiredAnnotation是通过匹配注解属性的⽅法。到之后进⾏两个操作:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论