All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.datalking.context.annotation.AutowiredAnnotationBeanPostProcessor Maven / Gradle / Ivy

The newest version!
package com.github.datalking.context.annotation;

import com.github.datalking.annotation.Autowired;
import com.github.datalking.annotation.Value;
import com.github.datalking.beans.PropertyValues;
import com.github.datalking.beans.TypeConverter;
import com.github.datalking.beans.factory.BeanFactory;
import com.github.datalking.beans.factory.BeanFactoryAware;
import com.github.datalking.beans.factory.BeanFactoryUtils;
import com.github.datalking.beans.factory.config.ConfigurableListableBeanFactory;
import com.github.datalking.beans.factory.config.DependencyDescriptor;
import com.github.datalking.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import com.github.datalking.beans.factory.config.RuntimeBeanReference;
import com.github.datalking.beans.factory.support.MergedBeanDefinitionPostProcessor;
import com.github.datalking.beans.factory.support.RootBeanDefinition;
import com.github.datalking.common.BridgeMethodResolver;
import com.github.datalking.common.GenericTypeResolver;
import com.github.datalking.common.MethodParameter;
import com.github.datalking.common.Ordered;
import com.github.datalking.common.PriorityOrdered;
import com.github.datalking.exception.BeanCreationException;
import com.github.datalking.util.AnnotationUtils;
import com.github.datalking.util.Assert;
import com.github.datalking.util.BeanUtils;
import com.github.datalking.util.ClassUtils;
import com.github.datalking.util.ReflectionUtils;
import com.github.datalking.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 自动注入bean到字段和setter方法
 * 会解析@Autowired和@Value
 *
 * @author yaoo on 5/28/18
 */
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
        implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {

    protected final Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * 支持自动注入的注解类型,默认3个@Autowired、@Vaule、@Inject
     */
    private final Set> autowiredAnnotationTypes = new LinkedHashSet<>();

    private String requiredParameterName = "required";

    private boolean requiredParameterValue = true;

    private int order = Ordered.LOWEST_PRECEDENCE - 2;

    private ConfigurableListableBeanFactory beanFactory;

    private final Map, Constructor[]> candidateConstructorsCache = new ConcurrentHashMap<>(64);

    private final Map injectionMetadataCache = new ConcurrentHashMap<>(64);

    public AutowiredAnnotationBeanPostProcessor() {

        this.autowiredAnnotationTypes.add(Autowired.class);
        this.autowiredAnnotationTypes.add(Value.class);

        try {

            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.
        }
    }

    public void setAutowiredAnnotationType(Class autowiredAnnotationType) {
        Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null");
        this.autowiredAnnotationTypes.clear();
        this.autowiredAnnotationTypes.add(autowiredAnnotationType);
    }

    public void setAutowiredAnnotationTypes(Set> autowiredAnnotationTypes) {
        Assert.notEmpty(autowiredAnnotationTypes.toArray(), "'autowiredAnnotationTypes' must not be empty");
        this.autowiredAnnotationTypes.clear();
        this.autowiredAnnotationTypes.addAll(autowiredAnnotationTypes);
    }

    public void setRequiredParameterName(String requiredParameterName) {
        this.requiredParameterName = requiredParameterName;
    }

    public void setRequiredParameterValue(boolean requiredParameterValue) {
        this.requiredParameterValue = requiredParameterValue;
    }

    public void setOrder(int order) {
        this.order = order;
    }

    public int getOrder() {
        return this.order;
    }

    public void setBeanFactory(BeanFactory beanFactory) {
        if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
            throw new IllegalArgumentException("AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory");
        }
        this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
    }


    /**
     * 构建autowire需要的元数据,加入缓存
     */
    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) {

        if (beanType != null) {

            // 查找bean的依赖项
            InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);

            // 添加进RootBeanDefinition
            metadata.checkConfigMembers(beanDefinition);
        }
    }

    @Override
    public Constructor[] determineCandidateConstructors(Class beanClass, String beanName) {

        // Quick check on the concurrent map first, with minimal locking.
        Constructor[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);

        if (candidateConstructors == null) {
            synchronized (this.candidateConstructorsCache) {
                candidateConstructors = this.candidateConstructorsCache.get(beanClass);

                if (candidateConstructors == null) {
                    Constructor[] rawCandidates = beanClass.getDeclaredConstructors();
                    List> candidates = new ArrayList<>(rawCandidates.length);

                    Constructor requiredConstructor = null;
                    Constructor defaultConstructor = null;

                    for (Constructor candidate : rawCandidates) {

                        Annotation ann = findAutowiredAnnotation(candidate);
                        if (ann != null) {

                            if (requiredConstructor != null) {
                                try {
                                    throw new Exception(beanName + "Invalid autowire-marked constructor: " + candidate + ". Found constructor with 'required' Autowired annotation already: " + requiredConstructor);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }

                            if (candidate.getParameterTypes().length == 0) {
                                throw new IllegalStateException("Autowired annotation requires at least one argument: " + candidate);
                            }

                            boolean required = determineRequiredStatus(ann);
                            if (required) {
                                if (!candidates.isEmpty()) {
                                    try {
                                        throw new Exception(beanName + "Invalid autowire-marked constructors: " + candidates + ". Found constructor with 'required' Autowired annotation: " + candidate);
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                }
                                requiredConstructor = candidate;
                            }

                            candidates.add(candidate);
                        } else if (candidate.getParameterTypes().length == 0) {
                            defaultConstructor = candidate;
                        }
                    }

                    if (!candidates.isEmpty()) {
                        // Add default constructor to list of optional constructors, as fallback.
                        if (requiredConstructor == null) {
                            if (defaultConstructor != null) {
                                candidates.add(defaultConstructor);
                            } else if (candidates.size() == 1 && logger.isWarnEnabled()) {
                                logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
                                        "': single autowire-marked constructor flagged as optional - this constructor " +
                                        "is effectively required since there is no default constructor to fall back to: " +
                                        candidates.get(0));
                            }
                        }
                        candidateConstructors = candidates.toArray(new Constructor[candidates.size()]);
                    } else {
                        candidateConstructors = new Constructor[0];
                    }

                    this.candidateConstructorsCache.put(beanClass, candidateConstructors);
                }
            }
        }

        return (candidateConstructors.length > 0 ? candidateConstructors : null);
    }

    /**
     * 解析属性占位符的入口,并注入属性
     */
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs,
                                                    PropertyDescriptor[] pds,
                                                    Object bean, String beanName) {

        // 获取beanName中依赖的其他bean,一般是带有@Autowired的字段
        InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
        try {

            // ==== 实现autowire的入口,将metadata中的依赖项注入bean的字段
            metadata.inject(bean, beanName, pvs);
        } catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
        }

        return pvs;
    }

    public void processInjection(Object bean) {
        Class clazz = bean.getClass();
        InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz, null);
        try {
            metadata.inject(bean, null, null);
        } catch (Throwable ex) {
            throw new BeanCreationException("Injection of autowired dependencies failed for class [" + clazz + "]", ex);
        }
    }

    /**
     * 查找beanName依赖注入的字段或方法
     */
    private InjectionMetadata findAutowiringMetadata(String beanName, Class clazz, PropertyValues pvs) {

        // 使用beanName或class全名作为缓存的key
        String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());

        // 从缓存中查找bean的依赖信息
        InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);

        /// 若metadata为空,即缓存中没有,则需刷新缓存
        if (InjectionMetadata.needsRefresh(metadata, clazz)) {
            synchronized (this.injectionMetadataCache) {
                metadata = this.injectionMetadataCache.get(cacheKey);
                if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                    if (metadata != null) {
                        metadata.clear(pvs);
                    }

                    // 构建clazz需要autowire的元数据,一般是提取@Autowired或@Value标注的字段
                    metadata = buildAutowiringMetadata(clazz);
                    this.injectionMetadataCache.put(cacheKey, metadata);
                }
            }
        }

        return metadata;
    }

    /**
     * 构建clazz需要autowire的元数据,一般是提取@Autowired或@Value标注的字段
     */
    private InjectionMetadata buildAutowiringMetadata(Class clazz) {
        LinkedList elements = new LinkedList<>();
        Class targetClass = clazz;

        do {
            LinkedList currElements = new LinkedList<>();

            /// 获取依赖注入的字段
            Field[] fs = targetClass.getDeclaredFields();
            for (Field field : fs) {

                // 提取字段的@Autowired或@Value注解,若无此注解,返回null
                Annotation ann = findAutowiredAnnotation(field);

                if (ann != null) {
                    if (Modifier.isStatic(field.getModifiers())) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Autowired annotation is not supported on static fields: " + field);
                        }
                        continue;
                    }

                    // 检查该字段是否必须,默认为true
                    boolean required = determineRequiredStatus(ann);
                    currElements.add(new AutowiredFieldElement(field, required));
                }
            }

            /// 获取依赖注入的方法
            Method[] ms = targetClass.getDeclaredMethods();
            for (Method method : ms) {
                Annotation ann = null;
                Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);

                if (BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {

                    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);
                        }
                        continue;
                    }
                    if (method.getParameterTypes().length == 0) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Autowired annotation should be used on methods with actual 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.getSuperclass();
        }
        while (targetClass != null && targetClass != Object.class);

        return new InjectionMetadata(clazz, elements);
    }

    /**
     * 提取字段的@Autowired或@Value注解
     */
    private Annotation findAutowiredAnnotation(AccessibleObject ao) {

        for (Class type : this.autowiredAnnotationTypes) {

            Annotation ann = AnnotationUtils.getAnnotation(ao, type);
            if (ann != null) {
                return ann;
            }
        }

        return null;
    }

    protected  Map findAutowireCandidates(Class type) {
        if (this.beanFactory == null) {
            throw new IllegalStateException("No BeanFactory configured - override the getBeanOfType method or specify the 'beanFactory' property");
        }
        return BeanFactoryUtils.beansOfTypeIncludingAncestors(this.beanFactory, type);
    }

    /**
     * 检查要注入的字段或方法是否是必须的
     */
    protected boolean determineRequiredStatus(Annotation ann) {
        try {

            Method method = ReflectionUtils.findMethod(ann.annotationType(), this.requiredParameterName);
            if (method == null) {
                // Annotations like @Inject and @Value don't have a method (attribute) named "required" -> default to required status
                return true;
            }

            return (this.requiredParameterValue == (Boolean) ReflectionUtils.invokeMethod(method, ann));
        } catch (Exception ex) {
            // An exception was thrown during reflective invocation of the required attribute -> default to required status
            return true;
        }
    }

    private void registerDependentBeans(String beanName, Set autowiredBeanNames) {
        if (beanName != null) {
            for (String autowiredBeanName : autowiredBeanNames) {
                if (this.beanFactory.containsBean(autowiredBeanName)) {
                    this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
                }

            }
        }
    }

    private Object resolvedCachedArgument(String beanName, Object cachedArgument) {

        if (cachedArgument instanceof DependencyDescriptor) {
            DependencyDescriptor descriptor = (DependencyDescriptor) cachedArgument;
            TypeConverter typeConverter = this.beanFactory.getTypeConverter();
            return this.beanFactory.resolveDependency(descriptor, beanName, null, typeConverter);
        } else if (cachedArgument instanceof RuntimeBeanReference) {

            return this.beanFactory.getBean(((RuntimeBeanReference) cachedArgument).getBeanName());
        } else {

            return cachedArgument;
        }
    }

    /**
     * 标注有@AutoWired注解的字段元信息
     * Class representing injection information about an annotated field.
     */
    private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {

        private final boolean required;

        private volatile boolean cached = false;

        private volatile Object cachedFieldValue;

        public AutowiredFieldElement(Field field, boolean required) {
            super(field, null);
            this.required = required;
        }

        /**
         * 注入依赖的字段
         */
        @Override
        protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {

            Field field = (Field) this.member;

            try {
                Object value;

                if (this.cached) {

                    value = resolvedCachedArgument(beanName, this.cachedFieldValue);
                } else {

                    DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
                    Set autowiredBeanNames = new LinkedHashSet<>(1);
                    TypeConverter typeConverter = beanFactory.getTypeConverter();

                    // ==== 创建作为依赖字段的对象,是实现autowire字段的入口,也可以注入字符串类型的字段,是解析@Value中占位符的入口
                    value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);

                    /// 加入缓存
                    synchronized (this) {
                        if (!this.cached) {
                            if (value != null || this.required) {
                                this.cachedFieldValue = desc;

                                registerDependentBeans(beanName, autowiredBeanNames);

                                if (autowiredBeanNames.size() == 1) {
                                    String autowiredBeanName = autowiredBeanNames.iterator().next();
                                    if (beanFactory.containsBean(autowiredBeanName)) {

                                        if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {

                                            this.cachedFieldValue = new RuntimeBeanReference(autowiredBeanName);
                                        }
                                    }
                                }
                            } else {
                                this.cachedFieldValue = null;
                            }
                            this.cached = true;
                        }
                    }
                }

                /// 设置字段的值,即完成属性注入
                if (value != null) {
                    ReflectionUtils.makeAccessible(field);
                    field.set(bean, value);
                }
            } catch (Throwable ex) {
                throw new BeanCreationException("Could not autowire field: " + field, ex);
            }
        }
    }


    /**
     * 标注有@AutoWired注解的方法元信息
     * Class representing injection information about an annotated method.
     */
    private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {

        private final boolean required;

        private volatile boolean cached = false;

        private volatile Object[] cachedMethodArguments;

        public AutowiredMethodElement(Method method, boolean required, PropertyDescriptor pd) {
            super(method, pd);
            this.required = required;
        }

        @Override
        protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
            if (checkPropertySkipping(pvs)) {
                return;
            }
            Method method = (Method) this.member;
            try {
                Object[] arguments;
                if (this.cached) {
                    // Shortcut for avoiding synchronization...
                    arguments = resolveCachedArguments(beanName);
                } else {
                    Class[] paramTypes = method.getParameterTypes();
                    arguments = new Object[paramTypes.length];
                    DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
                    Set autowiredBeanNames = new LinkedHashSet<>(paramTypes.length);
                    TypeConverter typeConverter = beanFactory.getTypeConverter();

                    for (int i = 0; i < arguments.length; i++) {
                        MethodParameter methodParam = new MethodParameter(method, i);

                        GenericTypeResolver.resolveParameterType(methodParam, bean.getClass());
                        descriptors[i] = new DependencyDescriptor(methodParam, this.required);

                        arguments[i] = beanFactory.resolveDependency(descriptors[i], beanName, autowiredBeanNames, typeConverter);

                        if (arguments[i] == null && !this.required) {
                            arguments = null;
                            break;
                        }
                    }
                    synchronized (this) {
                        if (!this.cached) {
                            if (arguments != null) {
                                this.cachedMethodArguments = new Object[arguments.length];
                                for (int i = 0; i < arguments.length; i++) {
                                    this.cachedMethodArguments[i] = descriptors[i];
                                }

                                registerDependentBeans(beanName, autowiredBeanNames);
                                if (autowiredBeanNames.size() == paramTypes.length) {
                                    Iterator it = autowiredBeanNames.iterator();

                                    for (int i = 0; i < paramTypes.length; i++) {
                                        String autowiredBeanName = it.next();

                                        if (beanFactory.containsBean(autowiredBeanName)) {

                                            if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
                                                this.cachedMethodArguments[i] = new RuntimeBeanReference(autowiredBeanName);
                                            }
                                        }
                                    }
                                }
                            } else {
                                this.cachedMethodArguments = null;
                            }
                            this.cached = true;
                        }
                    }
                }
                if (arguments != null) {
                    ReflectionUtils.makeAccessible(method);
                    method.invoke(bean, arguments);
                }
            } catch (InvocationTargetException ex) {
                throw ex.getTargetException();
            } catch (Throwable ex) {
                throw new BeanCreationException("Could not autowire method: " + method, ex);
            }
        }

        private Object[] resolveCachedArguments(String beanName) {
            if (this.cachedMethodArguments == null) {
                return null;
            }
            Object[] arguments = new Object[this.cachedMethodArguments.length];
            for (int i = 0; i < arguments.length; i++) {
                arguments[i] = resolvedCachedArgument(beanName, this.cachedMethodArguments[i]);
            }
            return arguments;
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy