目录
一、Spring 注入属性的方式
1.1 通过名称注入(Autowire.BY_NAME,默认Autowire.NO)
1.2 通过类型(Autowire.BY_TYPE)注入
1.3 通过@Autowired注入
一、Spring 注入属性的方式
1.1 通过名称注入(Autowire.BY_NAME,默认Autowire.NO)
@Component
public class Apple {
}
@Configuration
public class ByNameAutowaire {
//找对应Apple的set方法
@Bean(autowire = Autowire.BY_NAME)
public Fruit fruit(){
return new Fruit();
}
}
public class Fruit {
private Apple apple;
public Apple getApple() {
return apple;
}
public void setApple(Apple apple) {
this.apple = apple;
}
}
在Fruit中注入Apple属性,使用byName的方式,必须在Fruit中有对应的set()方法,在进行属性注入时,找的是set方法对应的bean的名字(比如setApple()方法找的就是apple这个bean对象)。在此时并没有进行属性的注入,而是将它放进了newPvs中,后续进行赋值。在找方法时需要如下的条件才满足(unsatisfiedNonSimpleProperties):
1. 必须要有set方法
2. pvs中不存在
3. 不是简单类型(CharSequence、Enum、Number、Date、Locale、URI、URL)
所以,以上几种类型使用@Bean(autowire = Autowire.BY_NAME)不会注入
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//从我们的bean定义中解析出我们的所有属性对象
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
//循环我们当前bean的属性
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
//显示的调用getBean所有属性的名称bean显示调用BeanFactory
Object bean = getBean(propertyName);
//把我们依赖的属性添加到pvs中
pvs.add(propertyName, bean);
//注册当前bean和属性依赖bean的依赖关系
registerDependentBean(propertyName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
--------------------------unsatisfiedNonSimpleProperties-------------------
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
Set result = new TreeSet<>();
//这个可以再后置处理器中设置 MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition
//MutablePropertyValues pvs = new MutablePropertyValues();
//pvs.add("apple", new Apple());
//beanDefinition.setPropertyValues(pvs);
PropertyValues pvs = mbd.getPropertyValues();
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
//set方法不为空||pd.getName=set的名字,pvs中不存在 ||不是简单属性则加入数组
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
//isSimpleProperty属性排除
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
result.add(pd.getName());
}
}
return StringUtils.toStringArray(result);
}
1.2 通过类型(Autowire.BY_TYPE)注入
@Configuration
public class ByTypeAutowaire {
//找对应Apple的set方法
@Bean(autowire = Autowire.BY_TYPE)
public Fruit fruit(){
return new Fruit();
}
}
原理和byName类似,byType则是去找参数对应的类型进行注入,放入对应的pvs中
1.3 通过@Autowired注入
@Component
public class Fruit {
private Apple apple;
@Autowired
public Apple getApple() {
return apple;
}
public void setApple(Apple apple) {
this.apple = apple;
}
}
spring在创建bean时通过后置处理器AutowiredAnnotationBeanPostProcessor对@Autowired属性进行解析(AbstractAutowireCapableBeanFactory.populateBean)
AutowiredAnnotationBeanPostProcessor继承关系如下所示:MergedBeanDefinitionPostProcessor后置处理器在推断构造函数调用后,进行调用postProcessMergedBeanDefinition方法,先于赋值属性调用。
通过findAutowiringMetadata方法找到带有Autowired注解的属性,并将对应的属性放入injectionMetadataCache中,方便后续在执行属性赋值的时候可直接从缓存中进行获取
private InjectionMetadata findAutowiringMetadata(String beanName, Class> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
//寻找对应方法加了@Autowired的
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
接下来看寻找@Autowired具体的方法(buildAutowiringMetadata)。遍历类的属性和方法看是否有@Value @Autowired @Inject注解如果有其中一个。并且不是static修饰的方法或者字段则构建AutowiredFieldElement、AutowiredMethodElement放入currElements集合中。
private InjectionMetadata buildAutowiringMetadata(final Class> clazz) {
List elements = new ArrayList<>();
Class> targetClass = clazz;
do {
final List currElements = new ArrayList<>();
//遍历字段
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// @Value @Autowired @Inject注解
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
//static不会给属性赋值
if (Modifier.isStatic(field.getModifiers())) {
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, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation should only 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 = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
在spring进行属性注入时,直接从缓存中取到之前解析的数据,分别对属性字段和方法进行注入即可。



