手写Mybatis整合Spring示例,原来Spring的扩展能力这么强大

本文探讨了Spring的加载上下文方式和多种扩展点,如ApplicationContextInitializer、BeanDefinitionRegistryPostProcessor等,详细解释了各个扩展点的用途和执行时机。此外,文章还介绍了如何利用这些扩展点进行Mybatis与Spring的整合,通过FactoryBean和ImportBeanDefinitionRegistrar实现Mapper接口的动态代理和注册。最后,提供了一个简易的整合示例。
摘要由CSDN通过智能技术生成

Spring之所以能打败其他所有同类型Java开发框架屹立不倒的重要原因之一就是提供很多扩展点,让其他组件和框架很容易就整合到Spring框架里,所以也就诞生很多基于Spring的二次开发项目,接下来我们一起聊聊Spring提供哪些扩展点,这篇文章只是简单说明扩展点但不深入,有兴趣的伙伴可以后续一起学习交流,本篇最后我们再进行一个Mybatis和Spring整合工程简易开发示例

Spring加载上下文方式

Spring加载容器上下文主要提供以下三大类方式,第一种基于配置类为常用的使用方式,
AnnotationConfigApplicationContext传入参数是一个Class数组也即是支持多个配置类

public class ApplicationDemo {
    public static void main(String[] args) {
        //基于配置类加载Spring上下文
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        Student student = applicationContext.getBean(Student.class);
        System.out.println(student);

        //基于项目路径xml加载Spring上下文
        ClassPathXmlApplicationContext applicationContextXml = new ClassPathXmlApplicationContext("spring.xml");
        student = applicationContextXml.getBean(Student.class);
        System.out.println(student);

        //基于文件系统绝对路径xml加载Spring上下文
        FileSystemXmlApplicationContext applicationContextFileXml = new FileSystemXmlApplicationContext("E://spring.xml");
        student = applicationContextXml.getBean(Student.class);
        System.out.println(student);
    }
}

@Configuration
@ComponentScan({"com.itxs.pojo","com.itxs.extend"})
public class MyConfig {
}
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this();
    register(componentClasses);
    refresh();
}

扩展点

ApplicationContextInitializer

这个是Spring Boot提供的扩展点,在整个 spring 容器在刷新之前初始化
ConfigurableApplicationContext 的回调接口,简单来说,就是在容器刷新之前调用此类的 initialize 方法。这个点允许用户自己扩展。用户可以在整个 spring 容器还没被初始化之前做过一些事情。可以想到的场景可能为,在最开始激活一些配置,或者利用这时候 class 还没被类加载器加载的时机,进行动态字节码注入等操作

public class MyApplicationContextInitializer implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        System.out.println("-----------------------MyApplicationContextInitializer initialize");
    }
}
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        //SpringApplication Main函数添加初始化器方式
        SpringApplication springApplication = new SpringApplication(MyApplication.class);
        springApplication.addInitializers(new MyApplicationContextInitializer());
        springApplication.run(args);
    }
}

第二种配置文件中的配置

context:
  initializer:
    classes: com.itxs.extend.MyApplicationContextInitializer

第三种SpringBoot的SPI扩展
---META-INF/spring.factories中配置

org.springframework.context.ApplicationContextInitializer=com.itxs.extend.MyApplicationContextInitializer

BeanDefinitionRegistryPostProcessor-bean定义注册后置处理器


BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口,BeanFactoryPostProcessor的作用是在bean的定义信息已经加载但还没有进行初始化的时候执行postProcessBeanFactory()的方法,BeanDefinitionRegistryPostProcessor是在BeanFactoryPostProcessor的前面执行,在bean定义之后提供的扩展点,比如可以在这里动态注册自己的 beanDefinition,加载 classpath 之外的 bean信息。

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        System.out.println("BeanDefinitionRegistryPostProcessor-postProcessBeanDefinitionRegistry");
        System.out.println("BeanDefinitionCount:"+beanDefinitionRegistry.getBeanDefinitionCount());
        String[] beanDefinitionNames = beanDefinitionRegistry.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println("beanDefinitionName:"+beanDefinitionName);
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("BeanDefinitionRegistryPostProcessor-postProcessBeanFactory");
    }
}

BeanFactoryPostProcessor-Bean工厂后置处理器

BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 的扩展接口,在 Spring 在读取 beanDefinition 信息之后实例化 bean 之前读取 bean 定义并可以修改它。在这个时机,用户可以通过实现这个扩展接口来自行处理一些东西,比如修改已经注册的 beanDefinition 的元信息。下面将student bean类型修改为teacher bean类型

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("BeanFactoryPostProcessor-postProcessBeanFactory");
        BeanDefinition student = configurableListableBeanFactory.getBeanDefinition("student");
        student.setBeanClassName(Teacher.class.getName());
    }
}

BeanPostProcessor-Bean后置处理器

该接口也可称为后置处理器,而我们Spring提供很多种bean后置处理器(比如在Spring源码中九大后置处理器九次调用后置处理器地方的说法),其作用是在Bean对象实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的业务逻辑;注意是Bean实例化完毕后及依赖注入完成后触发的;在这个扩展点我们可以修改bean的属性,可以给bean生成一个动态代理实例等等。Spring AOP的底层处理主要也是通过实现BeanPostProcessor来执行代理包装逻辑。方法中输入是一个个的bean,返回值则是bean修改的对象,默认为null则是不修改;bean后置处理器可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值