zoukankan      html  css  js  c++  java
  • Bean后置处理器

    创建完对象之后, 接下来, 就应该想办法对属性进行注入了, 其中就包括 @Autowired 注入

    但是在注入之前, 貌似 还没有对 @Autowired 进行扫描和解析.

    代码块:

    if (instanceWrapper == null) {
        /**
         * 创建 bean 实例,并将实例包裹在 BeanWrapper 实现类对象中返回。
         * createBeanInstance中包含三种创建 bean 实例的方式:
         *   1. 通过工厂方法创建 bean 实例
         *   2. 通过构造方法自动注入(autowire by constructor)的方式创建 bean 实例
         *   3. 通过无参构造方法方法创建 bean 实例
         *
         * 若 bean 的配置信息中配置了 lookup-method 和 replace-method,则会使用 CGLIB 增强 bean 实例。
         */
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }
    
    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                //调用属性合并后置处理器, 进行属性合并
                //这里会进行 一些注解 的扫描
                //CommonAnnotationBeanPostProcessor -> @PostConstruct @PreDestroy @Resource
                //AutowiredAnnotationBeanPostProcessor -> @Autowired @Value
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    接着看里面的内容

    protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof MergedBeanDefinitionPostProcessor) {
                MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
                bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
            }
        }
    }

    通过调试, 可以获取, 这里满足条件的, 有三个后置处理器, 按照调用先后顺序为: 

    1.CommonAnnotationBeanPostProcessor

    2.AutowiredAnnotationBeanPostProcessor

    3.ApplicationListenerDetector

    接下来看看里面都干了啥

    CommonAnnotationBeanPostProcessor

    这一步, 主要是扫描作用. 

    1. 扫描 @PostConstruct 和 @PreDestroy (这个很直观的能看到, 其无参构造函数中, 出现了这两个注解)

    2. 扫描 @Resource , 这个需要到 findResourceMetadata 中, 才能看到

    public CommonAnnotationBeanPostProcessor() {
        setOrder(Ordered.LOWEST_PRECEDENCE - 3);
        setInitAnnotationType(PostConstruct.class);
        setDestroyAnnotationType(PreDestroy.class);
        ignoreResourceType("javax.xml.ws.WebServiceContext");
    }
    
    /**
     * 1.遍历扫描方法上标注了 @PostConstruct  和 @PreDestroy 注解的类
     * 2.遍历扫描方法上标注了 @Resource 注解的类
     * @param beanDefinition
     * @param beanType
     * @param beanName
     */
    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
        InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
        metadata.checkConfigMembers(beanDefinition);
    }

    1. 调用父类方法, 进行@PostConstruct 和 @PreDestroy 扫描

    org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        LifecycleMetadata metadata = findLifecycleMetadata(beanType);
        metadata.checkConfigMembers(beanDefinition);
    }

    findLifecycleMetadata最终会调用 org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#buildLifecycleMetadata 方法

    private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
        List<LifecycleElement> initMethods = new ArrayList<>();
        List<LifecycleElement> destroyMethods = new ArrayList<>();
        Class<?> targetClass = clazz;
    
        do {
            final List<LifecycleElement> currInitMethods = new ArrayList<>();
            final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
    
            ReflectionUtils.doWithLocalMethods(targetClass, method -> {
                if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
                    LifecycleElement element = new LifecycleElement(method);
                    currInitMethods.add(element);
                    if (logger.isTraceEnabled()) {
                        logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
                    }
                }
                if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
                    currDestroyMethods.add(new LifecycleElement(method));
                    if (logger.isTraceEnabled()) {
                        logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
                    }
                }
            });
    
            initMethods.addAll(0, currInitMethods);
            destroyMethods.addAll(currDestroyMethods);
            //当前类解析完后, 拿到父类继续进行解析, 直到父类为 Object
            targetClass = targetClass.getSuperclass();
        }
        while (targetClass != null && targetClass != Object.class);
    
        return new LifecycleMetadata(clazz, initMethods, destroyMethods);
    }

    这里就是遍历类和其父类, 进行查找的.

    2. 进行 @Resource 扫描

    Resource 扫描, 是在本类中完成的.

    org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#findResourceMetadata

    private InjectionMetadata findResourceMetadata(String beanName, final 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.
        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) {
                        metadata.clear(pvs);
                    }
                    metadata = buildResourceMetadata(clazz);
                    this.injectionMetadataCache.put(cacheKey, metadata);
                }
            }
        }
        return metadata;
    }

    这里主要看 buildResourceMetadata( ) 方法.

    private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
        List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
        Class<?> targetClass = clazz;
    
        do {
            final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
    
            //扫描字段
            ReflectionUtils.doWithLocalFields(targetClass, field -> {
                if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
                    if (Modifier.isStatic(field.getModifiers())) {
                        throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
                    }
                    currElements.add(new WebServiceRefElement(field, field, null));
                }
                else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {
                    if (Modifier.isStatic(field.getModifiers())) {
                        throw new IllegalStateException("@EJB annotation is not supported on static fields");
                    }
                    currElements.add(new EjbRefElement(field, field, null));
                }
                else if (field.isAnnotationPresent(Resource.class)) {
                    //静态字段上标注 @Resource , 会抛异常
                    if (Modifier.isStatic(field.getModifiers())) {
                        throw new IllegalStateException("@Resource annotation is not supported on static fields");
                    }
                    if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
                        currElements.add(new ResourceElement(field, field, null));
                    }
                }
            });
    
            //扫描方法
            ReflectionUtils.doWithLocalMethods(targetClass, method -> {
                Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
                if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                    return;
                }
                if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                    if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
                        if (Modifier.isStatic(method.getModifiers())) {
                            throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
                        }
                        if (method.getParameterCount() != 1) {
                            throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
                        }
                        PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                        currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
                    }
                    else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) {
                        if (Modifier.isStatic(method.getModifiers())) {
                            throw new IllegalStateException("@EJB annotation is not supported on static methods");
                        }
                        if (method.getParameterCount() != 1) {
                            throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
                        }
                        PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                        currElements.add(new EjbRefElement(method, bridgedMethod, pd));
                    }
                    else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
                        if (Modifier.isStatic(method.getModifiers())) {
                            throw new IllegalStateException("@Resource annotation is not supported on static methods");
                        }
                        Class<?>[] paramTypes = method.getParameterTypes();
                        //如果目标方法, 没有参数, 或者有多个参数, 则抛出异常
                        if (paramTypes.length != 1) {
                            throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
                        }
                        if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
                            //这里拿到方法名, 会去跟类中的属性进行匹配
                            //匹配的规则是: method.equals(pd.getReadMethod()) || method.equals(pd.getWriteMethod())
                            //这个 readMethod 就是 getXXX 或 isXXX, writeMethod 就是 setXXX
                            //如果匹配不上, pd = null
                            PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                            currElements.add(new ResourceElement(method, bridgedMethod, pd));
                        }
                    }
                }
            });
    
            elements.addAll(0, currElements);
            targetClass = targetClass.getSuperclass();
        }
        while (targetClass != null && targetClass != Object.class);
    
        return new InjectionMetadata(clazz, elements);
    }

    注意到, 这里只进行了扫描转换工作, 并没有进行属性注入工作.

    AutowiredAnnotationBeanPostProcessor

    public AutowiredAnnotationBeanPostProcessor() {
        this.autowiredAnnotationTypes.add(Autowired.class);
        this.autowiredAnnotationTypes.add(Value.class);
        try {
            this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
                    ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
            logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
        }
        catch (ClassNotFoundException ex) {
            // JSR-330 API not available - simply skip.
        }
    }
    
    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
        metadata.checkConfigMembers(beanDefinition);
    }

    从这段代码, 可以猜测, 自动注入的类型, 是个集合, 这里有两个

    1. @Autowired

    2. @Value

    findAutowiringMetadata() 最终会调用本类方法: 

    org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata

    private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
        List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
        //需要处理的目标类
        Class<?> targetClass = clazz;
    
        do {
            final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
    
            // 通过反射获取该类所有的字段,并遍历每一个字段,通过方法 findAutowiredAnnotation 遍历每一个字段的所用注解,
            // 如果用autowired修饰了,则返回 auotowired 相关属性
            ReflectionUtils.doWithLocalFields(targetClass, field -> {
                AnnotationAttributes ann = findAutowiredAnnotation(field);
                if (ann != null) {
                    // 校验autowired注解是否用在了static方法上
                    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));
                }
            });
    
            //通过反射处理类的method
            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.isInfoEnabled()) {
                            logger.info("Autowired annotation is not supported on static methods: " + method);
                        }
                        return;
                    }
                    if (method.getParameterCount() == 0) {
                        if (logger.isInfoEnabled()) {
                            logger.info("Autowired annotation should only be used on methods with parameters: " +
                                    method);
                        }
                    }
                    boolean required = determineRequiredStatus(ann);
                    //这里也会进行属性的匹配, 按照规则 : method.equals(pd.getReadMethod()) || method.equals(pd.getWriteMethod())
                    //如果匹配不上, pd = null
                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                    currElements.add(new AutowiredMethodElement(method, required, pd));
                }
            });
    
            //用@Autowired修饰的注解可能不止一个,因此都加在 elements 这个容器里面,一起处理
            elements.addAll(0, currElements);
            targetClass = targetClass.getSuperclass();
        }
        while (targetClass != null && targetClass != Object.class);
    
        return new InjectionMetadata(clazz, elements);
    }

    这里也只是进行了扫描, 没有进行属性注入工作.

    ApplicationListenerDetector

    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        this.singletonNames.put(beanName, beanDefinition.isSingleton());
    }

    这个类也是挺能凑热闹的. 这里没有进行任何扫描工作. 只是记录了容器中的 bean 是否是单例模式.

    这里记录这个标志, 是为了后面用的. 对监听器进行过滤用的.

  • 相关阅读:
    一 基础--进制转化
    七牛云上传视频并截取第一帧为图片(js实现)
    FNScanner二维码接口openView自定义扫码Demo
    UIPickerView 模块示例demo
    vPlayer 模块Demo
    doT的高级用法及loadData的使用
    acmPush模块示例demo
    UIChatBox模块示例demo
    分享一款基于aui框架的图文发布界面
    基于js的APP多语言处理
  • 原文地址:https://www.cnblogs.com/elvinle/p/13371760.html
Copyright © 2011-2022 走看看