从源码层面带你实现一个自动注入注解
如何自己实现一个自动注入的注解
首先,需要了解到的是。Spring Bean 的生命周期
在生命周期中。注入bean属性的位置是在以下代码:
populateBean
位置中那么我们在项目中使用注解 产生一个bean的时候必定会经过以下代码进行一个bean的创建流程
/**省略代码**/ // 开始初始化 bean 实例对象 Object exposedObject = bean; try { // <5> 对 bean 进行填充,将各个属性值注入,其中,可能存在依赖于其他 bean 的属性 populateBean(beanName, mbd, instanceWrapper); // <6> 调用初始化方法 exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } /**省略代码**/
在生命周期中 populateBean 进行填充bean数据。把其他依赖引入进来
BeanPostProcessor 是一个bean创建时候的一个钩子。
以下代码 是循环调用实现了 BeanPostProcessor 子类
InstantiationAwareBeanPostProcessor#postProcessProperties
方法Spring 在以下代码中有自动注入的拓展点。 关键就是实现
InstantiationAwareBeanPostProcessor#postProcessProperties
/**省略代码**/ for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 对所有需要依赖检查的属性进行后处理 PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { // 从 bw 对象中提取 PropertyDescriptor 结果集 // PropertyDescriptor:可以通过一对存取方法提取一个属性 if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } /**省略代码**/
我们展开来讲一下 @Autowired 的实现是怎么样的吧:
实现类为
AutowiredAnnotationBeanPostProcessor.java
从上面可以得知,填充bean的时候。时调用了方法
ibp.postProcessPropertyValues()
那么
AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues()
则会被调用调用
findAutowiringMetadata
获取 class 以及父类 带有@Autowired
或者@Value
的属性或者方法:
/**省略代码**/ public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { // 获取所有可以注入的元数据 InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { // 注入数据 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; } private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { // 缓存名字获取 String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); // 获取是否已经读取过这个 class 类的 InjectionMetadata 有的话直接从缓存中获取出去 if (InjectionMetadata.needsRefresh(metadata, clazz)) { synchronized (this.injectionMetadataCache) { // 双重检查 metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { if (metadata != null) { metadata.clear(pvs); } // 构建自动注入的元数据 metadata = buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); } } } return metadata; } private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) { return InjectionMetadata.EMPTY; } Listelements = new ArrayList<>(); Class<?> targetClass = clazz; do { final ListcurrElements = new ArrayList<>(); // 循环 targetClass 的所有 field 并执 FieldCallback 逻辑 (函数式编程接口,传入的是一个执行函数) ReflectionUtils.doWithLocalFields(targetClass, field -> { // 获得字段上面的 Annotation 注解 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; } // 注解是否为必须依赖项 boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field, required)); } }); // 循环 targetClass 的所有 Method 并执 MethodCallback 逻辑 (函数式编程接口,传入的是一个执行函数) ReflectionUtils.doWithLocalMethods(targetClass, method -> { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } 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; } // 判断静态方法参数是否为0 if (method.getParameterCount() == 0) { if (logger.isInfoEnabled()) { logger.info("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 = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return InjectionMetadata.forElements(elements, clazz); } /**省略代码**/
真正注入数据的是
metadata.inject(bean, beanName, pvs);
调用的是
InjectionMetadata#inject
方法
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { CollectioncheckedElements = this.checkedElements; // 带有注解的方法或者属性列表 CollectionelementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements); if (!elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { element.inject(target, beanName, pvs); } } }
循环调用之前加入的带有注解的方法或者属性构建的对象
AutowiredFieldElement#inject
,AutowiredMethodElement#inject
/** * 属性上有注解 构建的处理对象 */ private class AutowiredFieldElement extends InjectionMetadata.InjectedElement { private final boolean required; private volatile boolean cached; @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 { // 获取属性名 Field field = (Field) this.member; Object value; // Bean 不是单例的话,会重复进入注入的这个操作, if (this.cached) { try { value = resolvedCachedArgument(beanName, this.cachedFieldValue); } catch (NoSuchBeanDefinitionException ex) { // Unexpected removal of target bean for cached argument -> re-resolve value = resolveFieldValue(field, bean, beanName); } } else { // 首次创建的时候进入该方法 value = resolveFieldValue(field, bean, beanName); } if (value != null) { // 属性如果不为public的话,则设置为可访问 ReflectionUtils.makeAccessible(field); field.set(bean, value); } } @Nullable private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) { // 构建DependencyDescriptor对象 DependencyDescriptor desc = new DependencyDescriptor(field, this.required); desc.setContainingClass(bean.getClass()); // 注入bean的数量。 有可能字段上是一个List SetautowiredBeanNames = new LinkedHashSet<>(1); Assert.state(beanFactory != null, "No BeanFactory available"); // 获得beanFactory类型转换类 TypeConverter typeConverter = beanFactory.getTypeConverter(); Object value; try { // 查找依赖关系 value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } synchronized (this) { if (!this.cached) { Object cachedFieldValue = null; if (value != null || this.required) { cachedFieldValue = desc; // 填入依赖关系 registerDependentBeans(beanName, autowiredBeanNames); // 判断如果注入依赖是只有一个 if (autowiredBeanNames.size() == 1) { String autowiredBeanName = autowiredBeanNames.iterator().next(); if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } this.cachedFieldValue = cachedFieldValue; this.cached = true; } } return value; } } /** * 方法上有注解 构建的处理对象 */ private class AutowiredMethodElement extends InjectionMetadata.InjectedElement { private final boolean required; private volatile boolean cached; @Nullable private volatile Object[] cachedMethodArguments; public AutowiredMethodElement(Method method, boolean required, @Nullable PropertyDescriptor pd) { super(method, pd); this.required = required; } @Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { // 检查属性是不会在之前就已经注入过了。如果主如果则不进行二次覆盖 if (checkPropertySkipping(pvs)) { return; } Method method = (Method) this.member; Object[] arguments; if (this.cached) { try { arguments = resolveCachedArguments(beanName); } catch (NoSuchBeanDefinitionException ex) { // Unexpected removal of target bean for cached argument -> re-resolve arguments = resolveMethodArguments(method, bean, beanName); } } else { // 首次创建的时候进入该方法 arguments = resolveMethodArguments(method, bean, beanName); } if (arguments != null) { try { // 属性如果不为public的话,则设置为可访问 ReflectionUtils.makeAccessible(method); // 调用方法 并传入参数 method.invoke(bean, arguments); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } } @Nullable private Object[] resolveCachedArguments(@Nullable String beanName) { Object[] cachedMethodArguments = this.cachedMethodArguments; if (cachedMethodArguments == null) { return null; } Object[] arguments = new Object[cachedMethodArguments.length]; for (int i = 0; i < arguments.length; i++) { arguments[i] = resolvedCachedArgument(beanName, cachedMethodArguments[i]); } return arguments; } @Nullable private Object[] resolveMethodArguments(Method method, Object bean, @Nullable String beanName) { // 获取方法上有几个参数 int argumentCount = method.getParameterCount(); Object[] arguments = new Object[argumentCount]; DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount]; SetautowiredBeans = new LinkedHashSet<>(argumentCount); Assert.state(beanFactory != null, "No BeanFactory available"); TypeConverter typeConverter = beanFactory.getTypeConverter(); for (int i = 0; i < arguments.length; i++) { // 方法参数,从方法参数中取出 i 构造 MethodParameter 对象 MethodParameter methodParam = new MethodParameter(method, i); DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required); currDesc.setContainingClass(bean.getClass()); descriptors[i] = currDesc; try { // 获取方法中 i 参数的内容 Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter); if (arg == null && !this.required) { arguments = null; break; } arguments[i] = arg; } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex); } } synchronized (this) { if (!this.cached) { if (arguments != null) { DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length); registerDependentBeans(beanName, autowiredBeans); if (autowiredBeans.size() == argumentCount) { Iteratorit = autowiredBeans.iterator(); Class<?>[] paramTypes = method.getParameterTypes(); for (int i = 0; i < paramTypes.length; i++) { String autowiredBeanName = it.next(); if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) { cachedMethodArguments[i] = new ShortcutDependencyDescriptor( descriptors[i], autowiredBeanName, paramTypes[i]); } } } this.cachedMethodArguments = cachedMethodArguments; } else { this.cachedMethodArguments = null; } this.cached = true; } } return arguments; } }
以上就是
@Autowired
实现的完整流程。 可概括为:
populateBean
->AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
-> 获取带有注解的属性和方法构建AutowiredFieldElement
,AutowiredMethodElement
对象,然后循环调用了inject
进行属性调用
自定义自动注入注解。
编写抽象类代码:
package com.yunlongn.common.core.autowired; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.PropertyValues; import org.springframework.beans.factory.*; import org.springframework.beans.factory.annotation.InjectionMetadata; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.annotation.MergedAnnotations; import org.springframework.lang.Nullable; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import java.beans.PropertyDescriptor; import java.lang.annotation.Annotation; import java.lang.reflect.*; import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** * 抽象的自动注入方法 * @author yunlgongn */ public abstract class AbstractAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor { private final Set> annotationTypes = new LinkedHashSet<>(4); private final MapinjectionMetadataCache = new ConcurrentHashMap<>(256); protected final Log logger = LogFactory.getLog(getClass()); /** * 处理的 annotationType 对象 * @return Annotation 自定义注解 */ public abstract Class<? extends Annotation> annotationType(); AbstractAnnotationBeanPostProcessor () { Class<? extends Annotation> annotation = this.annotationType(); annotationTypes.add(annotation); } @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName); } @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName); } @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { InjectionMetadata metadata = findAbstractMetadata(beanName, bean.getClass(), pvs); try { // 注入数据 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; } private InjectionMetadata findAbstractMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); // 获取是否已经读取过这个 class 类的 InjectionMetadata 有的话直接从缓存中获取出去 if (InjectionMetadata.needsRefresh(metadata, clazz)) { synchronized (this.injectionMetadataCache) { // 双重检查 metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { if (metadata != null) { metadata.clear(pvs); } metadata = buildAbstractMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); } } } return metadata; } private InjectionMetadata buildAbstractMetadata(final Class<?> clazz) { if (!AnnotationUtils.isCandidateClass(clazz, this.annotationTypes)) { return InjectionMetadata.EMPTY; } Listelements = new ArrayList<>(); Class<?> targetClass = clazz; do { final ListcurrElements = new ArrayList<>(); // 循环 targetClass 的所有 field 并执 FieldCallback 逻辑 (函数式编程接口,传入的是一个执行函数) ReflectionUtils.doWithLocalFields(targetClass, field -> { // 获得字段上面的 Annotation 注解 MergedAnnotation<?> ann = findAbstractAnnotation(field); if (ann != null) { // 判断是否为静态属性 如果是,则不进行注入 if (Modifier.isStatic(field.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Abstract annotation is not supported on static fields: " + field); } return; } currElements.add(new AbstractFieldElement(field, ann)); } }); //数据加到数组最前方 父类的的注解都放在靠前的位置 elements.addAll(0, currElements); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return InjectionMetadata.forElements(elements, clazz); } @Nullable private MergedAnnotation<?> findAbstractAnnotation(AccessibleObject ao) { // 将指定方法上的注解合并成一个注解 MergedAnnotations annotations = MergedAnnotations.from(ao); // 循环要扫描的注解 annotationTypes 那个在前面就认哪个 for (Class<? extends Annotation> type : this.annotationTypes) { MergedAnnotation<?> annotation = annotations.get(type); if (annotation.isPresent()) { return annotation; } } return null; } @Deprecated @Override public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) { return postProcessProperties(pvs, bean, beanName); } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName); } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return InstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); } /** * 实现交给子类进行实现 将注解透传出去 * @param mergedAnnotation 属性上的注解 * @param bean bean实例 * @param beanName bean的名字 * @param field 字段 * @param autowiredFieldElement 注解 * @return 注入对象 * @throws Exception */ protected abstract Object getInjectedObject(MergedAnnotation<?> mergedAnnotation, Object bean, String beanName, Field field, AbstractFieldElement autowiredFieldElement) throws Exception; public class AbstractFieldElement extends InjectionMetadata.InjectedElement { private final MergedAnnotation<?> mergedAnnotation; public AbstractFieldElement(Field field, MergedAnnotation<?> mergedAnnotation) { super(field, null); this.mergedAnnotation = mergedAnnotation; } @Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Field field = (Field) this.member; Object value = getInjectedObject(this.mergedAnnotation, bean, beanName, field, this); if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value); } } } }
抽象类实现,实现一个
@RedisAutowired
自定义注入注解
package com.yunlongn.common.core.autowired; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.core.annotation.MergedAnnotation; import java.lang.annotation.Annotation; import java.lang.reflect.Field; public class RedisAutowiredBeanPostProcessor extends AbstractAnnotationBeanPostProcessor implements BeanFactoryAware { private BeanFactory beanFactory = null; @Override public Class<? extends Annotation> annotationType() { return RedisAutowired.class; } @Override protected Object getInjectedObject(MergedAnnotation<?> mergedAnnotation, Object bean, String beanName, Field field, AbstractAnnotationBeanPostProcessor.AbstractFieldElement autowiredFieldElement) throws Exception { // 从value中获取bean的名字。 或者通过一些其他的逻辑获取名字 String s = mergedAnnotation.getString("value"); return beanFactory.getBean(s); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } }
在 Application 引入以上 @Import(RedisAutowiredBeanPostProcessor.class) 那么
@RedisAutowired
注解就生效了
@RedisAutowired("db102") private XXXService service;