Spring的注入模型

一、如何手动设置注入模型Spring的注入模型属于beanDefifinition的一个属性(默认为0),可以手动设置
xml设置
<bean id="n" class="xxxx" autowire="byType"> </bean> 
JAVA代码设置
public class ModelBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) beanFactory.getBeanDefinition("bean"); //获取注入模型//手动设置注入模型beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);}}二、Spring的四种注入模型【Spring的注入模型】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;}三、Autowired注解注入源码分析注:此处只分析注入的核心流程,细节不在此展开
通过
AutowiredAnnotationBeanPostProcessor的postProcessProperties方法完成对@Autowired注解的处理和解析

Spring的注入模型

文章插图
 

Spring的注入模型

文章插图
 
这里最终会将所有打了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;}// 判断注解中是否有 Requiredboolean 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);}}// 判断注解中是否有 Requiredboolean 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);}


推荐阅读