05beanfactory后置处理器

BeanFactory 后处理器的作用

作用与bdMap创建完成后,通过对bdMap的操作(新增)来实现更多的功能拓展

  • ConfigurationClassPostProcessor 可以解析

    • @ComponentScan

    • @Bean

    • @Import

    • @ImportResource

  • MapperScannerConfigurer 可以解析

    • Mapper 接口

  1. @ComponentScan, @Bean, @Mapper 等注解的解析属于核心容器(即 BeanFactory)的扩展功能

  2. 这些扩展功能由不同的 BeanFactory 后处理器来完成,其实主要就是补充了一些 bean 定义

package com.butch.a05;

import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

public class A05 {

    public static void main(String[] args) {
        GenericApplicationContext applicationContext = new GenericApplicationContext();
        applicationContext.registerBean("config",Config.class);

        //注册beanfactory后置处理器ConfigurationClassPostProcessor 解析// @ComponentScan @Bean @Import @ImportResource
        applicationContext.registerBean(ConfigurationClassPostProcessor.class);
        //注册MapperScannerConfigurer,解析@mapperScaner
        applicationContext.registerBean(MapperScannerConfigurer.class,beanDefinition -> {
            beanDefinition.getPropertyValues().add("basePackage","com.butch.a05.mapper");
        });
        applicationContext.refresh();

        for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
            System.out.println("beanDefinitionName = " + beanDefinitionName);
        }
        applicationContext.close();
    }
}
package com.butch.a05;

import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
@ComponentScan("com.butch.a05.component")
public class Config {
    @Bean
    public Bean1 bean1() {
        return new Bean1();
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        return sqlSessionFactoryBean;
    }

    @Bean(initMethod = "init")
    public DruidDataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl("jdbc:mysql://localhost:3306/db1");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");
        return dataSource;
    }

    /*@Bean
    public MapperFactoryBean<Mapper1> mapper1(SqlSessionFactory sqlSessionFactory) {
        MapperFactoryBean<Mapper1> factory = new MapperFactoryBean<>(Mapper1.class);
        factory.setSqlSessionFactory(sqlSessionFactory);
        return factory;
    }

    @Bean
    public MapperFactoryBean<Mapper2> mapper2(SqlSessionFactory sqlSessionFactory) {
        MapperFactoryBean<Mapper2> factory = new MapperFactoryBean<>(Mapper2.class);
        factory.setSqlSessionFactory(sqlSessionFactory);
        return factory;
    }*/
}
package com.butch.a05;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Bean1 {

    private static final Logger log = LoggerFactory.getLogger(Bean1.class);

    public Bean1() {
        log.debug("Bean1 我被 Spring 管理啦");
    }
}

package com.butch.a05.component;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class Bean2 {

    private static final Logger log = LoggerFactory.getLogger(Bean2.class);

    public Bean2() {
        log.debug("Bean2 我被 Spring 管理啦");
    }
}

模拟解析 @ComponentScan

  1. Spring 操作元数据的工具类 CachingMetadataReaderFactory

  2. 通过注解元数据(AnnotationMetadata)获取直接或间接标注的注解信息

  3. 通过类元数据(ClassMetadata)获取类名,AnnotationBeanNameGenerator 生成 bean 名

  4. 解析元数据是基于 ASM 技术

版本1.0未解耦
package com.butch.a05;

import com.fasterxml.jackson.dataformat.xml.util.AnnotationUtil;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

import java.io.IOException;

public class A05 {

    public static void main(String[] args) throws IOException {
        GenericApplicationContext applicationContext = new GenericApplicationContext();
        applicationContext.registerBean("config",Config.class);

//        //注册beanfactory后置处理器ConfigurationClassPostProcessor 解析// @ComponentScan @Bean @Import @ImportResource
//        applicationContext.registerBean(ConfigurationClassPostProcessor.class);
//        //注册MapperScannerConfigurer,解析@mapperScaner
//        applicationContext.registerBean(MapperScannerConfigurer.class,beanDefinition -> {
//            beanDefinition.getPropertyValues().add("basePackage","com.butch.a05.mapper");
//        });
        //模拟componscan注解
        ComponentScan annotation = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
        if (annotation != null){
            //获取包名
            for (String s : annotation.basePackages()) {
                System.out.println("s = " + s);
                //转化路径为包名
                // com.butch.a05.component -> classpath*:com/butch/a05/component/**/*.class
                String path = "classpath*:" + s.replace(".", "/") + "/**/*.class";
                System.out.println("path = " + path);
                //通过context扩展获取资源, 获取扫描到包class文件集合
                CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
                AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
                Resource[] resources = applicationContext.getResources(path);
                for (Resource resource : resources) {
//                    System.out.println("resource = " + resource);
                    //获取类的元信息
                    MetadataReader metadataReader = factory.getMetadataReader(resource);
                    System.out.println("metadataReader.getClassMetadata().getClassName() = " + metadataReader.getClassMetadata().getClassName());
                    System.out.println("metadataReader.getAnnotationMetadata().hasAnnotatedMethods(Component.class.getName()) = " + metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName()));
                    //派生注解
                    System.out.println("metadataReader.getAnnotationMetadata().hasAnnotatedMethods(Component.class.getName()) = " + metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));
                    //当加了component注解或者其派生注解的时候 注册bd到map中
                    if (metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName()) || metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName())){
                        //构造一个bd
                        AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName()).getBeanDefinition();
                        //获取bean的名字
                        String beanName = generator.generateBeanName(bd, applicationContext);
                        //注册bd
                        applicationContext.registerBeanDefinition(beanName,bd);
                    }
                }

            }
        }
        applicationContext.refresh();

        for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
            System.out.println("beanDefinitionName = " + beanDefinitionName);
        }
        applicationContext.close();
    }

}
版本2.0解耦
package com.butch.a05;

import com.fasterxml.jackson.dataformat.xml.util.AnnotationUtil;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

import java.io.IOException;

public class A05 {

    public static void main(String[] args) throws IOException {
        GenericApplicationContext applicationContext = new GenericApplicationContext();
        applicationContext.registerBean("config",Config.class);

//        //注册beanfactory后置处理器ConfigurationClassPostProcessor 解析// @ComponentScan @Bean @Import @ImportResource
//        applicationContext.registerBean(ConfigurationClassPostProcessor.class);
//        //注册MapperScannerConfigurer,解析@mapperScaner
//        applicationContext.registerBean(MapperScannerConfigurer.class,beanDefinition -> {
//            beanDefinition.getPropertyValues().add("basePackage","com.butch.a05.mapper");
//        });
        applicationContext.registerBean(ComponentScanPostProcessor.class);

        applicationContext.refresh();

        for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
            System.out.println("beanDefinitionName = " + beanDefinitionName);
        }
        applicationContext.close();
    }

}
package com.butch.a05;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

public class ComponentScanPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry applicationContext) throws BeansException {
        //模拟componscan注解
        try {
            ComponentScan annotation = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
            if (annotation != null) {
                //获取包名
                for (String s : annotation.basePackages()) {
                    System.out.println("s = " + s);
                    //转化路径为包名
                    // com.butch.a05.component -> classpath*:com/butch/a05/component/**/*.class
                    String path = "classpath*:" + s.replace(".", "/") + "/**/*.class";
                    System.out.println("path = " + path);
                    //通过context扩展获取资源, 获取扫描到包class文件集合
                    CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
                    AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
//                    Resource[] resources = applicationContext.getResources(path);
                    Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
                    for (Resource resource : resources) {
//                    System.out.println("resource = " + resource);
                        //获取类的元信息
                        MetadataReader metadataReader = factory.getMetadataReader(resource);
                        System.out.println("metadataReader.getClassMetadata().getClassName() = " + metadataReader.getClassMetadata().getClassName());
                        System.out.println("metadataReader.getAnnotationMetadata().hasAnnotatedMethods(Component.class.getName()) = " + metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName()));
                        //派生注解
                        System.out.println("metadataReader.getAnnotationMetadata().hasAnnotatedMethods(Component.class.getName()) = " + metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));
                        //当加了component注解或者其派生注解的时候 注册bd到map中
                        if (metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName()) || metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName())) {
                            //构造一个bd
                            AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName()).getBeanDefinition();
                            //获取bean的名字
                            String beanName = generator.generateBeanName(bd, applicationContext);
                            //注册bd
                            applicationContext.registerBeanDefinition(beanName, bd);
                        }
                    }

                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override// context.refresh
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}
总结
  1. 获取componentScan注解的basepage属性值,即为包名,并将其转为路径

  2. 获取类路径下的所有资源类文件,获取其元数据

  3. 根据其元数据判断类中是否有component注解及其派生注解

  4. 有的话注册bd到map中

模拟解析 @Bean

版本1.0未解耦
package com.butch.a05;

import com.fasterxml.jackson.dataformat.xml.util.AnnotationUtil;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Set;

public class A05 {

    public static void main(String[] args) throws IOException {
        GenericApplicationContext applicationContext = new GenericApplicationContext();
        applicationContext.registerBean("config",Config.class);

//        //注册beanfactory后置处理器ConfigurationClassPostProcessor 解析// @ComponentScan @Bean @Import @ImportResource
//        applicationContext.registerBean(ConfigurationClassPostProcessor.class);
//        //注册MapperScannerConfigurer,解析@mapperScaner
//        applicationContext.registerBean(MapperScannerConfigurer.class,beanDefinition -> {
//            beanDefinition.getPropertyValues().add("basePackage","com.butch.a05.mapper");
//        });

//        applicationContext.registerBean(ComponentScanPostProcessor.class);

        //获取类元信息
        CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
        MetadataReader metadataReader = factory.getMetadataReader(new ClassPathResource("com/butch/a05/Config.class"));
        //所有包含@bean注解的方法
        Set<MethodMetadata> annotatedMethods = metadataReader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
        for (MethodMetadata method : annotatedMethods) {
            System.out.println("annotatedMethod = " + method.getMethodName());
            //获取工厂bd
            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();
            String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();
            beanDefinitionBuilder.setFactoryMethodOnBean(method.getMethodName(),"config");
            beanDefinitionBuilder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
            //处理属性提取注入的初始化
            if (initMethod.length() > 0){
                beanDefinitionBuilder.setInitMethodName(initMethod);
            }
            //注册bd
            AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
            applicationContext.registerBeanDefinition(method.getMethodName(),beanDefinition);
        }
        applicationContext.refresh();

        for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
            System.out.println("beanDefinitionName = " + beanDefinitionName);
        }
        applicationContext.close();
    }

}
版本2.0解耦
package com.butch.a05;

import com.fasterxml.jackson.dataformat.xml.util.AnnotationUtil;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Set;

public class A05 {

    public static void main(String[] args) throws IOException {
        GenericApplicationContext applicationContext = new GenericApplicationContext();
        applicationContext.registerBean("config",Config.class);

//        //注册beanfactory后置处理器ConfigurationClassPostProcessor 解析// @ComponentScan @Bean @Import @ImportResource
//        applicationContext.registerBean(ConfigurationClassPostProcessor.class);
//        //注册MapperScannerConfigurer,解析@mapperScaner
//        applicationContext.registerBean(MapperScannerConfigurer.class,beanDefinition -> {
//            beanDefinition.getPropertyValues().add("basePackage","com.butch.a05.mapper");
//        });

//        applicationContext.registerBean(ComponentScanPostProcessor.class);

//        //获取类元信息
//        CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
//        MetadataReader metadataReader = factory.getMetadataReader(new ClassPathResource("com/butch/a05/Config.class"));
//        //所有包含@bean注解的方法
//        Set<MethodMetadata> annotatedMethods = metadataReader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
//        for (MethodMetadata method : annotatedMethods) {
//            System.out.println("annotatedMethod = " + method.getMethodName());
//            //获取工厂bd
//            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();
//            String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();
//            beanDefinitionBuilder.setFactoryMethodOnBean(method.getMethodName(),"config");
//            beanDefinitionBuilder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
//            //处理属性提取注入的初始化
//            if (initMethod.length() > 0){
//                beanDefinitionBuilder.setInitMethodName(initMethod);
//            }
//            //注册bd
//            AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
//            applicationContext.registerBeanDefinition(method.getMethodName(),beanDefinition);
//        }
        applicationContext.registerBean(AtBeanPostProcessor.class);
        applicationContext.refresh();

        for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
            System.out.println("beanDefinitionName = " + beanDefinitionName);
        }
        applicationContext.close();
    }

}
package com.butch.a05;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;

import java.io.IOException;
import java.util.Set;

public class AtBeanPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        try {
            //获取类元信息
            CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
            MetadataReader metadataReader = factory.getMetadataReader(new ClassPathResource("com/butch/a05/Config.class"));
            //所有包含@bean注解的方法
            Set<MethodMetadata> annotatedMethods = metadataReader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
            for (MethodMetadata method : annotatedMethods) {
                System.out.println("annotatedMethod = " + method.getMethodName());
                //获取工厂bd
                BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();
                String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();
                beanDefinitionBuilder.setFactoryMethodOnBean(method.getMethodName(),"config");
                beanDefinitionBuilder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
                //处理属性提取注入的初始化
                if (initMethod.length() > 0){
                    beanDefinitionBuilder.setInitMethodName(initMethod);
                }
                //注册bd
                AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
                beanDefinitionRegistry.registerBeanDefinition(method.getMethodName(),beanDefinition);
            }
        }catch (IOException e){
            e.printStackTrace();
        }

    }

    @Override//refresh
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}
总结
  1. 获取该类的元数据

  2. 获取类中所有标注@bean注解的方法

  3. 根据方法构造bd,注册到Map中

模拟解析@mapperscan

添加单个mapper可以使用@bean
  @Bean
    public MapperFactoryBean<Mapper1> mapper1(SqlSessionFactory sqlSessionFactory) {
        MapperFactoryBean<Mapper1> factory = new MapperFactoryBean<>(Mapper1.class);
        factory.setSqlSessionFactory(sqlSessionFactory);
        return factory;
    }

    @Bean
    public MapperFactoryBean<Mapper2> mapper2(SqlSessionFactory sqlSessionFactory) {
        MapperFactoryBean<Mapper2> factory = new MapperFactoryBean<>(Mapper2.class);
        factory.setSqlSessionFactory(sqlSessionFactory);
        return factory;
    }
扫描添加mapper
package com.butch.a05;

import org.mybatis.spring.mapper.MapperFactoryBean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;

import java.io.IOException;

public class MapperPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        try {

            //获取mapper对应的资源
            PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            Resource[] resources = resolver.getResources("classpath:com/butch/a05/mapper/**/*.class");
            CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
            AnnotationBeanNameGenerator annotationBeanNameGenerator = new AnnotationBeanNameGenerator();
            for (Resource resource : resources) {
                //获取资源元数据
                MetadataReader reader = factory.getMetadataReader(resource);
                ClassMetadata classMetadata = reader.getClassMetadata();
                //如果该类是一个接口则注册bd
                if (classMetadata.isInterface()){
                    AbstractBeanDefinition bd1 = BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class)
                            //mapper的泛型类型
                            .addConstructorArgValue(classMetadata.getClassName())
                            //set构造bytype
                            .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)
                            .getBeanDefinition();
                    //由于bean名字生成都是MapperFactoryBean,因此根据泛型类型再生成一个bd获取名字
                    AbstractBeanDefinition bd2 = BeanDefinitionBuilder.genericBeanDefinition(classMetadata.getClassName()).getBeanDefinition();
                    //获取名字
                    String beanName = annotationBeanNameGenerator.generateBeanName(bd2, beanDefinitionRegistry);
                    //注册
                    beanDefinitionRegistry.registerBeanDefinition(beanName,bd1);
                }

            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}
总结
  1. 单个mapper可以使用@bean注入

  2. 多个mapper使用mapperscan

    1. 获取mapperscan的包转为类路径,并获取资源

    2. 获取资源的下类的元信息

    3. 根据类元信息判断类是否为接口,是否有mapper注解

    4. 有则注册mpper,由于获取名字的时候使用的mapperfactorybean,获取到的名字都一样,因新建一个bd,根据类的元信息获取beanname

  • 12
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Bean的后置处理器是一种特殊的接口,即BeanPostProcessor接口。它定义了两个方法:postProcessBeforeInitialization和postProcessAfterInitialization。\[1\]这两个方法分别在Bean的初始化之前和之后被调用,可以在这两个方法中对Bean进行一些额外的处理操作。在Spring容器中,BeanFactory和ApplicationContext对待Bean的后置处理器有一些不同。ApplicationContext容器会自动检测配置文件中实现了BeanPostProcessor接口的类,并将其注册为后置处理器,而BeanFactory容器需要通过代码显式注册后置处理器。\[2\]后置处理器可以用来修改Bean的属性或行为,例如在postProcessAfterInitialization方法中根据条件修改Bean的属性值。\[3\]通过实现BeanPostProcessor接口并重写相应的方法,我们可以自定义后置处理器来对Bean进行额外的处理。 #### 引用[.reference_title] - *1* [spring源码-bean的后置处理器](https://blog.csdn.net/sunqingzhong44/article/details/128284663)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [SpringBeanPostProcessor(后置处理器)介绍](https://blog.csdn.net/qq_38526573/article/details/88086752)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [[spring学习]5、bean的后置处理器(BeanPostProcessor)](https://blog.csdn.net/m0_51545690/article/details/125189749)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值