怎样自己实现一个自动注入的注解
<hr>
- 首先,需要相识到的是。Spring Bean 的生命周期
- 在生命周期中。注入bean属性的位置是在以下代码:populateBean 位置中
- 那么我们在项目中使用注解 产生一个bean的时候必定会经过以下代码进行一个bean的创建流程
/**省略代码**/// 开始初始化 bean 实例对象Object exposedObject = bean;try { // 对 bean 进行添补,将各个属性值注入,其中,可能存在依赖于其他 bean 的属性 populateBean(beanName, mbd, instanceWrapper); // 调用初始化方法 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; } List elements = new ArrayList(); Class targetClass = clazz; do { final List currElements = 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 { Collection checkedElements = this.checkedElements; // 带有注解的方法大概属性列表 Collection elementsToIterate = (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 Set autowiredBeanNames = 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 = resolvedCachedArgument(beanName, cachedMethodArguments); } 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]; Set autowiredBeans = 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 = currDesc; try { // 获取方法中 i 参数的内容 Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter); if (arg == null && !this.required) { arguments = null; break; } arguments = 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) { Iterator it = 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)) { cachedMethodArguments = new ShortcutDependencyDescriptor( descriptors, autowiredBeanName, paramTypes); } } } 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 targetClass = clazz; do { final List currElements = 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 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 |