首页 > 其他分享 >05beanfactory后置处理器

05beanfactory后置处理器

时间:2024-06-02 20:02:55浏览次数:14  
标签:applicationContext 后置 factory springframework 05beanfactory org import class 处理器

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

标签:applicationContext,后置,factory,springframework,05beanfactory,org,import,class,处理器
From: https://blog.csdn.net/weixin_48254383/article/details/139304955

相关文章

  • 利用Linux系统提供的和调度器相关的接口让进程或线程对某个处理器进行绑定
    目录设置进程与CPU的亲和性设置线程与CPU的亲和性设置进程与CPU的亲和性taskset命令允许你查看或设置运行中的进程的CPU亲和性(即该进程可以在哪些CPU上运行)。要将一个已经运行的进程(例如PID为1234的进程)绑定到CPU0和CPU1上,你可以使用:taskset-cp0,11234如果你正在启动一......
  • 关于css预处理器sass详解
    Sass(SyntacticallyAwesomeStylesheets)是一种强大的CSS预处理器,旨在简化CSS的编写并增强其功能。以下是对Sass的详细解释,包括其特点、功能、语法格式以及使用方式。1.Sass的特点扩展CSS功能:Sass在CSS的基础上增加了变量、嵌套、混合(mixins)、继承等高级功能,使得CSS的编......
  • springboot基本使用十一(自定义全局异常处理器)
    例如:我们都知道在java中被除数不能为0,为0就会报byzero错误@RestControllerpublicclassTestController{@GetMapping("/ex")publicIntegerex(){inta=10/0;returna;}}打印结果:如何将这个异常进行处理?创建全局异常处理类......
  • 【SCAU操作系统】实验三单处理器系统的进程调度python源代码及实验报告参考
    一、课程设计目的        1.加深对进程概念的理解,明确进程和程序的区别。        2.深入了解系统如何组织进程、创建进程。        3.进一步认识如何实现处理器调度。二、课程设计内容        编写程序完成单处理器系......
  • C语言-----前置++和后置++的不同
    #include<stdio.h>intmain(){inta,b,c;a=5;c=++a;b=++c,c++,++a,a++;b+=a+++c;printf("a=%db=%dc=%d\n:",a,b,c);return0;}/*1、逗号运算符的优先级比赋值运算符=号的优先级低2、++、+的优先级比+=......
  • 探索SCSS:让CSS开发更高效的预处理器
    在现代前端开发中,CSS预处理器已成为不可或缺的工具。SCSS(SassyCSS)作为Sass的一种语法扩展,结合了Sass的强大功能和CSS的简洁语法,使得编写样式变得更加灵活和高效。本文将详细介绍SCSS的特点、使用方法以及最佳实践,帮助开发者更好地掌握这一强大的工具。一、SCSS简介SCSS是......
  • [处理器芯片]-2 CPU架构
    CPU有多种架构,例如x86,ARM,RISC-V,不同的架构定义了不同的指令集架构(ISA,InstructionSetArchitecture)。ISA通常包括数据处理指令(数学运算、逻辑运算、比较、移位等)、数据搬运、控制流指令(程序执行地址的跳转);从宏观角度ISA可以分为CISC(复杂指令集计算)和RISC(精简指令集计算)两种不同......
  • 认识NXP新型微处理器:MCX工业和物联网微控制器
    目录概述1 MCX工业和物联网微控制器介绍2 MCX系列微控制器类型2.1 MCXN系列微控制器2.1.1主要特征2.1.2MCXN系列产品2.1.3 MCXN9xx和N5xxMCU选型表2.2 MCXA系列微控制器 2.2.1主要特征2.2.2 MCXA系列产品2.2.3 MCXAMCU的架构2.3  MCXW系列......
  • 解决tiktok切换前后置虚拟摄像头卡住问题
    背景介绍:本人原先是android逆向工程师,后来因为工作变动,离开了协议分析这类的岗位,目前在做直播机与第三方应用兼容性分析相关分析。所以就有了这篇兼容性分析文章。本文篇幅较长,需要跟着思路一直往下看,否则肯定云里雾里,第一次发表长文,有很多不足的地方,请各位大佬指正,小弟在此谢......
  • 12代处理器在虚拟机中安装Windows98SE
    最近想把以前写的那个Windows98开始菜单完善一下,装个Windows98来参考参考。项目地址:https://github.com/zhaotianff/WindowsX.git路过的小伙伴可以帮忙点个star。  这里把安装过程分享一下。本文以VMware17虚拟机为例,介绍如何在12代处理器中安装Windows98SE。安装步骤......