Spring的注入模型属于beanDefifinition的一个属性(默认为0),可以手动设置
xml设置
<bean id="n" class="xxxx" autowire="byType"> </bean>
JAVA代码设置
public class ModelBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) beanFactory.getBeanDefinition("bean"); //获取注入模型
//手动设置注入模型
beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
}
}
public interface AutowireCapableBeanFactory extends BeanFactory {
/**
* Constant that indicates no externally defined autowiring. Note that
* BeanFactoryAware etc and annotation-driven injection will still be Applied.
* @see #createBean
* @see #autowire
* @see #autowireBeanProperties
*/
/**
* 默认的装配模式,如果注入indexBean,没有在属性上加@Autowired或者@Resource,这时候,indexBean是无法注入的
*/
int AUTOWIRE_NO = 0;
/**
* Constant that indicates autowiring bean properties by name
* (applying to all bean property setters).
* @see #createBean
* @see #autowire
* @see #autowireBeanProperties
*/
/**
* 通过属性名自动装配。Spring寻找与需要自动连接的属性同名的bean。
* 例如,如果一个bean定义按名称设置为自动装配,并且它包含一个master属性(也就是说,它有一个setMaster(…)方法),
* Spring就会查找一个名为master的bean定义,并使用它来设置属性。
*/
int AUTOWIRE_BY_NAME = 1;
/**
* Constant that indicates autowiring bean properties by type
* (applying to all bean property setters).
* @see #createBean
* @see #autowire
* @see #autowireBeanProperties
*/
/**
* 如果容器中恰好存在该属性类型的一个bean,则自动连接该属性。
* 如果存在多个,将抛出一个致命异常,这表明您不能对该bean使用byType自动装配。
* 如果没有匹配的bean,则什么也不会发生(属性没有设置)。
*/
int AUTOWIRE_BY_TYPE = 2;
/**
* Constant that indicates autowiring the greediest constructor that
* can be satisfied (involves resolving the appropriate constructor).
* @see #createBean
* @see #autowire
*/
/**
* 类似于byType,但适用于构造函数参数。
* 如果容器中没有确切的构造函数参数类型的bean,则会引发致命错误。
*/
int AUTOWIRE_CONSTRUCTOR = 3;
/**
* Constant that indicates determining an appropriate autowire strategy
* through introspection of the bean class.
* @see #createBean
* @see #autowire
* @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,
* prefer annotation-based autowiring for clearer demarcation of autowiring needs.
*/
/**
* 通过bean的内省来选择合适的自动装配策略(根据英文翻译,就是spring会选择最适合装备的策略)
*/
@Deprecated
int AUTOWIRE_AUTODETECT = 4;
}
注:此处只分析注入的核心流程,细节不在此展开
通过
AutowiredAnnotationBeanPostProcessor的postProcessProperties方法完成对@Autowired注解的处理和解析
这里最终会将所有打了Autowiring注解的字段和方法全部构建成
InjectionMetadata.InjectedElement放入一个set集合中进行处理
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
/**
* 遍历类中的所有属性字段
*/
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// 查询是否有 Autowired 注解
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 判断注解中是否有 Required
boolean required = determineRequiredStatus(ann);
// 封装成 AutowiredFieldElement 放入 currElements 集合
currElements.add(new AutowiredFieldElement(field, required));
}
});
/**
* 遍历类中所有方法
*/
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPAIr(method, bridgedMethod)) {
return;
}
// 查询是否有 Autowired 注解
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
// 判断注解中是否有 Required
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
// 封装成 AutowiredMethodElement 放入 currElements 集合
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
之后在调用
org.springframework.beans.factory.annotation.InjectionMetadata#inject方法进行属性填充
其中
AutowiredAnnotationBeanPostProcessor类里面有3个内部类,其中2个类为AutowiredFieldElement和AutowiredMethodElement,这2个类封装了对打在字段上或者方法上的@Autowired注解进行处理的逻辑;
我们就根据AutowiredFieldElement字段上的@Autowired注解进行分析,这个也是我们最常用的方式;
入口方法为inject方法,就是上面InjectionMetadata遍历调用的inject方法;
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency
org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
// 获取依赖的类型
Class<?> type = descriptor.getDependencyType();
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
/**
* 解析当前依赖是否支持多个bean注入,如:list、set、map类型等
* 如果支持多个bean注入,则在内部就完成bean的查找,不为空直接返回
*/
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
/**
* 根据类型查询bean实例,可能会有多个,key为需要注入对象的名字
*/
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// 判断在依赖上面是否加了必须的条件,默认为true
if (isRequired(descriptor)) {
// 抛出异常
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
// 如果非必须则返回null,不注入任何对象
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 如果找出的实例大于1个
if (matchingBeans.size() > 1) {
// 通过依赖描述组件来推断需要注入对象的名字
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
// 通过名字获取对象
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
// 如果找出来的实例为1个,则直接获取出来,赋值给instanceCandidate
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
// 判断是否为Class,如果是则说明没有实例化
if (instanceCandidate instanceof Class) {
// 实例化
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
// 将获取到的实例候选赋值给result
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
先根据类型查找bean;如果没有找到则报错(默认情况下@Autowired是一定需要注入一个bean的);如果查找到一个则用找到的这一个完成注入;如果查找到多个,先把这个多个放到map当中,继而根据属性的名字从map当中去获取;能获取到则使用获取的这个;如果map当中通过名字还是无法获取则报错;
@Autowired不会改变bean的注入模型(默认情况下bean的注入模型还是0);@Autowired算是一种半自动注入;因为他只需要程序员告诉spring需要注入的属性或者方法,而不需要程序员告诉spring需要注入的属性或者方法他的值到底是哪个bean;@Autowired会根据自己的规则去查找这个bean,所以只能算作半自动注入;
通过
CommonAnnotationBeanPostProcessor这个类的postProcessorProperties方
法来完成对@Resource注解的解析和处理
后续的流程和Autowired差不多,就是扫描出来类所有加了Resource注解的属性,封装成对应的
InjectionMetadata.InjectedElement
在封装成ResourceElement时会读取注解中的值进行参数的赋值
在调用ResourceElement的inject方法进行属性注入,但我们发现ResourceElement没有inject方法,我们就可以猜想出,这个方法肯定继承至父类
我们最终在
InjectionMetadata.InjectedElement中找到了inject方法
在调用子类ResourceElement的getResourceToInject方法
判断Resource是否自定义了名字,如果自定义了,则不会走类型查询并注入,而是会走else因为自定义了名字说明我们想根据名字注入对象;
如果没有自定义会先根据名字判断是否在单例池中存在或者在beanDefinitionMap中存在,存在则通过名字获取,没有则在通过类型去获取,获取到一个则进行注入,没有获取到或者获取到多个则抛异常;
@Resource在没有配置name的情况下首先根据名字查找;
如果名字能查找到则返回这个查找到的(spring容器的原则是name唯一的,所以不存在通过名字能查找到多个的情况);
如果通过名字查找不到(需要注意的是这里的前提是没有配置name的情况,spring觉得名字无所谓);因为对名字无要求,所以会再根据类型查找;那么走的就是@Autowired这一套;
如果配置了名字,spring觉得对名字有严格要求,所以只能根据你配置的名字查找;如果查找不到则报错,找到了则用;