大数据架构师 潜水
  • 1发帖数
  • 1主题数
  • 0关注数
  • 0粉丝
开启左侧

从源码层面带你实现一个自动注入注解

[复制链接]
大数据架构师 发表于 2021-9-13 21:07:50 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

                               
登录/注册后可看大图

怎样自己实现一个自动注入的注解

<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
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

猜你喜欢
在线客服邮箱
wxcy#wkgb.net

邮箱地址#换为@

Powered by 创意电子 ©2018-现在 专注资源实战分享源码下载站联盟商城