众所周知,Spring的依赖注入(DI)对Spring IOC 有着举足轻重的作用,是Spring灵魂所在。本篇文章就从日常开发中最常用的注解@Autowired开始,着手分析Spring是如何通过它们将Bean所需的外部资源注入其中.
@Autowired可以应用在 非静态字段、非静态方法、构造器上面注入bean。
@Configuration
public class AnnotationDependencyInjectionResolutionDemo {
// DependencyDescriptor ->
// 必须(required=true)
// 实时注入(eager=true)
// 通过类型(User.class)
// 字段名称("user")
// 是否首要(primary = true)
@Autowired(required = false) // 依赖查找(处理)
private User user;
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类) -> Spring Bean
applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载 XML 资源,解析并且生成 BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 依赖查找 QualifierAnnotationDependencyInjectionDemo Bean
AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);
// 期待输出 superUser Bean
System.out.println("demo.user = " + demo.user);
applicationContext.close();
}
}
xml中的
首先,我们看@Autowired的定义里可以发现,它是通过AutowiredAnnotationBeanPostProcessor去实现解析的
/*
* @author Juergen Hoeller
* @author Mark Fisher
* @author Sam Brannen
* @since 2.5
* @see AutowiredAnnotationBeanPostProcessor
* @see Qualifier
* @see Value
*/
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* Defaults to {@code true}.
*/
boolean required() default true;
}
AutowiredAnnotationBeanPostProcessor
在看一下AutowiredAnnotationBeanPostProcessor
它的继承图表:
由此继承图标我们能得出如下结论:
解析@Resource
注解的不是这个类,而是CommonAnnotationBeanPostProcessor
,但本文只会以AutowiredAnnotationBeanPostProcessor
为例做深入分析~~~(解析@Autowired
)
AutowiredAnnotationBeanPostProcessor 中属性
// 该处理器支持解析的注解们~~~(这里长度设置为4)
// 默认支持的是3个(当然你可以自己添加自定义的依赖注入的注解 这点非常强大)
private final Set> autowiredAnnotationTypes = new LinkedHashSet<>();
// @Autowired(required = false)这个注解的属性值名称
private String requiredParameterName = "required";
// 这个值一般请不要改变(若改成false,效果required = false的作用是相反的了)
private boolean requiredParameterValue = true;
private int order = Ordered.LOWEST_PRECEDENCE - 2;
@Nullable
private ConfigurableListableBeanFactory beanFactory;
// 对@Lookup方法的支持 本文不讨论
private final Set lookupMethodsChecked = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
// 构造函数注入,本文也不讨论
private final Map, Constructor[]> candidateConstructorsCache = new ConcurrentHashMap<>(256);
// 方法注入、字段filed注入 本文的重中之重
// 此处InjectionMetadata这个类非常重要,到了此处@Autowired注解含义已经没有了,完全被准备成这个元数据了
// 所以方便我们自定义注解的支持~~~优秀
// InjectionMetadata持有targetClass、Collection injectedElements等两个重要属性
// 其中InjectedElement这个抽象类最重要的两个实现为:AutowiredFieldElement和AutowiredMethodElement
private final Map injectionMetadataCache = new ConcurrentHashMap<>(256);
AutowiredAnnotationBeanPostProcessor执行构造方法时集合autowiredAnnotationTypes中依次放入了三个注解类@Autowired、@Value和JSR-330标准的@Inject
// 这是它唯一构造函数 默认支持下面三种租借(当然@Inject需要额外导包)
// 请注意:此处@Value注解也是被依赖注入解析的~~~~~~~~
// 当然如果你需要支持到你的自定义注解,你还可以调用下面的set方法添加。
@SuppressWarnings("unchecked")
public AutowiredAnnotationBeanPostProcessor() {
//后置处理器将处理@Autowire注解
this.autowiredAnnotationTypes.add(Autowired.class);
//后置处理器将处理@Value注解
this.autowiredAnnotationTypes.add(Value.class);
try {
//后置处理器将处理javax.inject.Inject JSR-330注解
this.autowiredAnnotationTypes.add((Class)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
两个setAutowiredAnnotationType是用于实现自定义依赖注入注解类型,首先它会把autowiredAnnotationTypes里面的元素全部clear,然后加入自定义的依赖注入注解类型,所以我们要注意在实现自定义注解注入时,这里会先把默认的注解类型清除
/**
* 这两个setAutowiredAnnotationType是用于实现自定义依赖注入注解类型,
* 首先它会把autowiredAnnotationTypes里面的元素全部clear,
* 然后加入自定义的依赖注入注解类型,所以我们要注意在实现自定义注解注入时,这里会先把默认的注解类型清除
*/
public void setAutowiredAnnotationType(Class autowiredAnnotationType) {
Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null");
this.autowiredAnnotationTypes.clear();
this.autowiredAnnotationTypes.add(autowiredAnnotationType);
}
第一个非常重要的核心方法,它负责:
1、解析@Autowired等注解然后转换
2、把注解信息转换为InjectionMetadata然后缓存到上面的injectionMetadataCache里面
postProcessMergedBeanDefinition的执行时机非常早,在doCreateBean()前部分完成bean定义信息的合并
// 第一个非常重要的核心方法~~~
//它负责1、解析@Autowired等注解然后转换
// 2、把注解信息转换为InjectionMetadata然后缓存到上面的injectionMetadataCache里面
// postProcessMergedBeanDefinition的执行时机非常早,在doCreateBean()前部分完成bean定义信息的合并
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
// 方法名为查找到该bean的依赖注入元信息,内部只要查找到了就会加入到缓存内,下次没必要再重复查找了~
// 它是一个模版方法,真正做事的方法是:buildAutowiringMetadata
// 它复杂把标注有@Autowired注解的属性转换为Metadata元数据信息 从而消除注解的定义
// 此处查找包括了字段依赖注入和方法依赖注入~~~
//获取给定类的autowire相关注解元信息
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.
//首先从容器中查找是否有给定类的autowire相关注解元信息
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) {
//解析给定类autowire相关注解元信息
metadata.clear(pvs);
}
//解析给定类autowire相关注解元信息
metadata = buildAutowiringMetadata(clazz);
//将得到的给定类autowire相关注解元信息存储在容器缓存中
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
// 这里我认为是整个依赖注入前期工作的精髓所在,简单粗暴的可以理解为:
// 它把以依赖注入都转换为InjectionMetadata元信息,待后续使用
// 这里会处理字段注入、方法注入~~~
// 注意:Autowired使用在static字段/方法上、0个入参的方法上(不会报错 只是无效)
// 显然方法的访问级别、是否final都是可以正常被注入进来的~~~
//解析给定类autowire相关注解元信息
private InjectionMetadata buildAutowiringMetadata(final Class clazz) {
//创建一个存放注解元信息的集合
LinkedList elements = new LinkedList<>();
Class targetClass = clazz;
//递归遍历当前类及其所有基类,解析全部注解元信息
do {
//创建一个存储当前正在处理类注解元信息的集合
final LinkedList currElements = new LinkedList<>();
//利用JDK反射机制获取给定类中所有的声明字段,获取字段上的注解信息
ReflectionUtils.doWithLocalFields(targetClass, field -> {
//获取给定字段上的注解
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;
}
//判断注解的required属性值是否有效
boolean required = determineRequiredStatus(ann);
//将当前字段元信息封装,添加在返回的集合中
currElements.add(new AutowiredFieldElement(field, required));
}
});
//利用JDK反射机制获取给定类中所有的声明方法,获取方法上的注解信息
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);
}
}
//判断注解的required属性值是否有效
boolean required = determineRequiredStatus(ann);
//获取当前方法的属性描述符,即方法是可读的(readable)getter方法,还是可写的(writeable)setter方法
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
//将方法元信息封装添加到返回的元信息集合中
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
//将当前类的注解元信息存放到注解元信息集合中
elements.addAll(0, currElements);
//获取给定类的父类
targetClass = targetClass.getSuperclass();
}
//如果给定类有基类,并且基类不是Object,则递归获取其基类的元信息
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
这一步,借助postProcessMergedBeanDefinition()方法完成了对该bean中所有的依赖注入的属性、方法及其父类的属性、方法进行合并Mergerd完成了原始元信息的转换,已经把依赖注入的相关注解全都转换成了InjectionMetadata,这样后面的使用过程中将不再需要再和具体注解打交道,而是做着一些和业务无关的动作即可。接下来进入注入阶段
这是核心阶段,也是最为复杂的阶段,当然前面的解析已经为本步骤做好了元数据的铺垫。
我们知道在Bean的创建过程中,完成Bean的实例化后,会调用方法AbstractAutowireCapableBeanFactory#populateBean()完成对Bean的属性赋值,从而就会触发InstantiationAwareBeanPostProcessor.postProcessPropertyValues()方法给属性进行赋值,这处也就是本步骤的入口。
围绕着这个模板方法postProcessPropertyValues, 我们回到AutowiredAnnotationBeanPostProcessor,找到postProcessPropertyValues的重写:
//处理类中的属性
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
//获取指定类中autowire相关注解的元信息
// 从缓存中取出这个bean对应的依赖注入的元信息
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//对Bean的属性进行自动注入
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
综上能够发现核心InjectionMetadata#inject(),最终依赖注入实际做事的是InjectedElement
,这个抽象类有好几个实现,此处我们以使用最为广泛的AutowiredFieldElement
进行说明
这个类继承自静态抽象内部类InjectionMetadata.InjectedElement,并且它还是AutowiredAnnotationBeanPostProcessor的private内部类,体现出非常高的内聚性:
// 它的宿主类是AutowiredAnnotationBeanPostProcessor 高内聚低耦合
private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
private final boolean required;
private volatile boolean cached = false;
@Nullable
private volatile Object cachedFieldValue;
//唯一构造方法
public AutowiredFieldElement(Field field, boolean required) {
super(field, null); // 此处显示调用父类的构造函数
this.required = required;
}
// 核心方法:字段的依赖注入
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// 显然此处父类的member就指的是filed
Field field = (Field) this.member;
Object value;
// 走缓存,关于cachedFieldValue的值 且听下文分解
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
} else {
// 每个Field都包装成一个DependencyDescriptor
// 如果是Method包装成DependencyDescriptor,毕竟一个方法可以有多个入参
// 此处包装成它后,显然和元数据都无关了,只和Field有关了 完全隔离
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
// 转换器使用的bean工厂的转换器~~~
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
// 获取依赖的value值的工作 最终还是委托给beanFactory.resolveDependency()去完成的~~~~
// 这个接口方法由AutowireCapableBeanFactory提供,它提供了从bean工厂里获取依赖值的能力~
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
// 下面代码是把缓存值缓存起来 让同一个Field注入多次能提高效率
synchronized (this) {
if (!this.cached) {
// 可以看到value!=null并且required=true才会进行缓存的处理
// 按照上例 此处value值为A@2277实例
if (value != null || this.required) {
this.cachedFieldValue = desc; // 可以看到缓存的值是上面的DependencyDescriptor对象~~~~
// 这个方法是宿主类AutowiredAnnotationBeanPostProcessor的方法
// 简单的说就是注册到bean工厂去,比如此处b是依赖a的 所以就注册这个依赖关系进去了
// 参考this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
registerDependentBeans(beanName, autowiredBeanNames);
// autowiredBeanNames里可能会有别名的名称~~~所以size可能大于1
if (autowiredBeanNames.size() == 1) {
// beanFactory.isTypeMatch挺重要的~~~~因为@Autowired是按照类型注入的
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName, field.getType());
}
}
} else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
// 不为null,就完成最终的set值 利用反射给filed属性赋值~~~~
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
前面准备好的注解的、需要注入的元数据信息,这一步使用执行注入。
从源码中也能发现一个特点,Spring大量的使用到了转换、适配、委托等机制。因此最终最最最重要的一行代码无非是这一句:
//根据容器中Bean定义,解析指定的依赖关系,获取依赖对象
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
委托AutowireCapableBeanFactory
来获取到依赖值value,从而最终完成注入(反射执行注入~)。
so,其实最核心还是在Bean工厂里,也就是它的唯一内建实现类DefaultListableBeanFactory。
我们跟进这里的beanFactory.resolveDependency,进入DefaultListableBeanFactory, 这个方法有个重要的入参DependencyDescriptor:
/**
* Descriptor for a specific dependency that is about to be injected.
* Wraps a constructor parameter, a method parameter or a field,
* allowing unified access to their metadata.
*
* @author Juergen Hoeller
* @since 2.5
*/
@SuppressWarnings("serial")
public class DependencyDescriptor extends InjectionPoint implements Serializable {
//被申明的类,也就是注入的容器
private final Class declaringClass;
@Nullable //方法注入名 这里可为空 因为不都是方法注入
private String methodName;
@Nullable //参数类型
private Class[] parameterTypes;
//参数索引顺序
private int parameterIndex;
@Nullable //字段注入的字段名
private String fieldName;
//是否必需
private final boolean required;
//是否是饥饿的 对应@Lazy
private final boolean eager;
//嵌入层次
private int nestingLevel = 1;
@Nullable
private Class containingClass;
@Nullable //类型处理
private transient volatile ResolvableType resolvableType;
@Nullable//类型描述 描述类型相关的内容
private transient volatile TypeDescriptor typeDescriptor;
通过DependencyDescriptor 的每个描述字段可以大致猜到注入的user依赖对应的相关描述
// DependencyDescriptor ->
// 必须(required=true)
// 实时注入(eager=true)
// 通过类型(User.class)
// 字段名称("user")
// 是否首要(primary = true)
@Autowired(required = false) // 依赖查找(处理)
private User user;
在resolveDependency里面debug, 观察DependencyDescriptor 里的值和猜测的基本一致 :
回到resolveDependency方法:
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//此处使用的是DefaultParameterNameDiscoverer 来获取参数名
// 这就是为什么我们使用@Autowired注入,
// 即使有多个同类型的Bean,也可以通过field属性名进行区分的根本原因(可以不需要使用@Qualifier注解)
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 支持Optional 原来还是doResolveDependency 暂略
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
//支持ObjectFactory和ObjectProvider(延迟注入)
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
// 绝大部分情况下 肯定走到这里~~~~
// 此处特别特别的需要重视:这是@Lazy支持的根本原因~~
// 关于AutowireCandidateResolver我建议小伙伴先看下一个章节~~~
// 此处若通过AutowireCandidateResolver解析到了值就直接返回了(若标注了@Lazy,此处的result将不会为null了~~~)
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
// doResolveDependency是绝大多数情况下 最终会去执行的代码(若result仍旧为null的话)
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
(重中之重)
绝大多数情况下,肯定会经由我们的doResolveDependency()方法来处理,因此这个方法的实现才是重中之重。其实getLazyResolutionProxyIfNecessary()它的底层依赖还是doResolveDependency()这个方法
看看DefaultListableBeanFactory对这个"重中之重"的实现:
// 此处autowiredBeanNames是在inject的一个空的Set
// autowired表示最终可以注入进去的bean名称们(因为可能是会有多个符合条件的)
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set 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();
// 拿到@Value注解的value值(是个字符串) 若没有标注@Value 显然就不用那啥了
// 从此处其实也可以看出,@Value注解的优先级对于找到bean来说还是蛮高的
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
// ============ 这部分主要是解析@Value注解
// 解析它的占位符,解析它的SpEL表达式
// 相关处理类曹靠BeanExpressionResolver和StandardBeanExpressionResolver StandardEvaluationContext等
// 因为关于@Value的文章里详细解过,此处一笔带过~~~
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());
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
// 此处处理的是多值注入的情况,比如注入Stream
其实本类的doResolveDependency()方法使用非常的广泛,虽然不属于接口方法,但是在DefaultListableBeanFactory类中还是public的访问权限。
Spring使用了大量的委托代理还有模板方法等,实现了高内聚低耦合的特点。整个对@Autowired依赖注入的流程分为两个周期,第一个是解析元信息并放入缓存中,第二个周期是注入,
每个阶段有每个阶段的核心,解析元信息核心是模仿双亲委派的父类优先的原则去合并BeanDefition, 并全部转换成InjectionMetadata, 第二个阶段就是InjectionMetadata的inject方法的实现,其中会涉及到beanFactory.resolveDependency,这里可以处理多种注入类型的封装,包括Optional、ObjectFactory、ObjectProvider和jsr330 里面的依赖注入方案,最后处理默认注入操作,最终通过反射将值设置到字段当中。
与@Autowired等效的@Resource注解虽然注入效果一样,但是是通过另一个BeanPostProcessor–CommonAnnotationBeanPostProcessor去实现的,实现流程大同小异,提供对jdk注入注解和ejb WebServiceRef等注入注解的支持。
CommonAnnotationBeanPostProcessor 调用优先级高于AutowiredAnnotationBeanPostProcessor。
基于AutowiredAnnotationBeanPostProcessor 实现
自定义实现
• 生命周期处理
• InstantiationAwareBeanPostProcessor
• MergedBeanDefinitionPostProcessor
• 元数据
• InjectedElement
• InjectionMetadata
/**
* 自定义注解(元标注 @Autowired)
*
* @author
* @since
*/
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Autowired
public @interface MyAutowired {
/**
* Declares whether the annotated dependency is required.
* Defaults to {@code true}.
*/
boolean required() default true;
}
4.2、通过、AutowiredAnnotationBeanPostProcessor
/**
* 自定义依赖注入注解
*
* @author
* @since
*/
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InjectedUser {
}
//注意这里要设置成static,不然依赖注入会失效,
// 因为这个AutowiredAnnotationBeanPostProcessor定义在当前demo类中,
// 想要拿到自定义的AutowiredAnnotationBeanPostProcessor,就必须实例化demo类
//但是在实例化demo类LeonAutowired也同时被处理了,
// 此时还没有自定义的AutowiredAnnotationBeanPostProcessor,因此不认识@LeonAutowired,
//因此被注入了null。然后等实例化完了之后自定义的AutowiredAnnotationBeanPostProcessor才拿到
@Bean
@Order(Ordered.LOWEST_PRECEDENCE - 3)
@Scope
public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {
AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
beanPostProcessor.setAutowiredAnnotationType(InjectedUser.class);
return beanPostProcessor;
}