ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring 高级 工厂后处理器模拟实现-Mapper

2022-08-28 14:04:42  阅读:207  来源: 互联网

标签:Mapper core Spring factory springframework 处理器 context org import


一、源方式自动注入

package com.mangoubiubiu.show.a05;

import com.alibaba.druid.pool.DruidDataSource;
import com.mangoubiubiu.show.a05.component.Bean2;
import com.mangoubiubiu.show.a05.mapper.Mapper1;
import com.mangoubiubiu.show.a05.mapper.Mapper2;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperFactoryBean;
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.mangoubiubiu.show.a05.component")
public class Config {


    @Bean
    public Bean1 bean1(){
        return new Bean1();
    }

    public Bean2 bean2(){
        return new Bean2();
    }

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


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

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

}
package com.mangoubiubiu.show.a05;

import com.mangoubiubiu.show.a05.component.ComponentScanPostProcessor;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.JmxEnabled;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
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.AnnotationMetadata;
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.awt.*;
import java.io.IOException;
import java.util.List;
import java.util.Set;

@Slf4j
public class A05Application {

    private MetadataReader reader;

    public static void main(String[] args) throws IOException {
        GenericApplicationContext context = new GenericApplicationContext();
        //将config注册到容器里面
        context.registerBean("config",Config.class);
//        context.registerBean(ComponentScanPostProcessor.class);
//        context.registerBean(MapperScannerConfigurer.class,beanDefinition -> {
//            beanDefinition.getPropertyValues().add("basePackage","com.mangoubiubiu.show.a05.mapper");
//        });

        context.registerBean(AtBeanPostProcessor.class);

        //初始化容器

        context.refresh();

        for (String name: context.getBeanDefinitionNames()) {
            System.out.println(name);
        }

        context.close();
    }



}

发现Mapper1 Mapper2 确实被注入进来了

二、自己Bean后处理器将Mapper注入到容器中

package com.mangoubiubiu.show.a05;

import lombok.SneakyThrows;
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;

public class MyMapperPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @SneakyThrows
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources("classpath:com/mangoubiubiu/show/a05/mapper/**/*.class");
        CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
        AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
        for (Resource resource : resources) {
            MetadataReader metadataReader = factory.getMetadataReader(resource);
            //得到类的源信息
            ClassMetadata classMetadata = metadataReader.getClassMetadata();
            //如果当前类是接口
            if(classMetadata.isInterface()){
                AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class)
                        //加进class  的类名
                        .addConstructorArgValue(classMetadata.getClassName())
                        //设置自动装配
                        .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)
                        .getBeanDefinition();
                String beanName = generator.generateBeanName(beanDefinition, beanFactory);
                generator.generateBeanName(beanDefinition, beanFactory);
                beanFactory.registerBeanDefinition(beanName,beanDefinition);

            }


        }


    }

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

    }
}
package com.mangoubiubiu.show.a05;

import com.mangoubiubiu.show.a05.component.ComponentScanPostProcessor;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.JmxEnabled;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
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.AnnotationMetadata;
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.awt.*;
import java.io.IOException;
import java.util.List;
import java.util.Set;

@Slf4j
public class A05Application {

    private MetadataReader reader;

    public static void main(String[] args) throws IOException {
        GenericApplicationContext context = new GenericApplicationContext();
        //将config注册到容器里面
        context.registerBean("config",Config.class);
//        context.registerBean(ComponentScanPostProcessor.class);
//        context.registerBean(MapperScannerConfigurer.class,beanDefinition -> {
//            beanDefinition.getPropertyValues().add("basePackage","com.mangoubiubiu.show.a05.mapper");
//        });

//        context.registerBean(AtBeanPostProcessor.class); //解析bean
        context.registerBean(MyMapperPostProcessor.class);
        //初始化容器

        context.refresh();

        for (String name: context.getBeanDefinitionNames()) {
            System.out.println(name);
        }

        context.close();
    }



}

运行发现报错了,为啥会报错了,因为此时 

这个Bean组件并没有注入到IOC容器里面,所有我们自定义的Processor自动装配失败了。

解决方案:开启我们上次写的解析Bean的 Proceesor就行啦

但是发现Mapper1 和 Mapper2 并没有注入进来,

Bean的名称是根据bean定义里面的一些信息去生成名字 而我们要注入的Mapper有2个 第一个注入后Bean名字叫mapperFactoryBean,第二个Bean注入后由于BeanDefinition里面的信息相同,生成的Bean的名字也叫mapperFactoryBean,2个相同bean名的组件,后生成的bean会把前面的bean给覆盖掉 所以这里只生成一个叫mapperFactoryBean的Bean。

三、解决方案

根据接口生成BeanDefinition就行啦

package com.mangoubiubiu.show.a05;

import lombok.SneakyThrows;
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;

public class MyMapperPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @SneakyThrows
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources("classpath:com/mangoubiubiu/show/a05/mapper/**/*.class");
        CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
        AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
        for (Resource resource : resources) {
            MetadataReader metadataReader = factory.getMetadataReader(resource);
            //得到类的源信息
            ClassMetadata classMetadata = metadataReader.getClassMetadata();
            //如果当前类是接口
            if(classMetadata.isInterface()){
                AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class)
                        //加进class  的类名
                        .addConstructorArgValue(classMetadata.getClassName())
                        //设置自动装配
                        .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)
                        .getBeanDefinition();
                //根据Mapper接口生成 beanDefinition
                AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(classMetadata.getClassName()).getBeanDefinition();
                String beanName = generator.generateBeanName(bd, beanFactory);
                generator.generateBeanName(beanDefinition, beanFactory);
                beanFactory.registerBeanDefinition(beanName,beanDefinition);

            }


        }


    }

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

    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

标签:Mapper,core,Spring,factory,springframework,处理器,context,org,import
来源: https://www.cnblogs.com/mangoubiubiu/p/16632633.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有