Spring5 底层原理 常见beanFactory后处理器(黑马)

BeanFactory 后处理器

演示 - BeanFactory 后处理器的作用

代码参考

A05

package com.itheima.a05;

import com.itheima.a05.mapper.Mapper1;
import com.itheima.a05.mapper.Mapper2;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanNameGenerator;
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.Map;
import java.util.Set;

/*
    BeanFactory 后处理器的作用
 */


public class A05 {
    private static final Logger log = LoggerFactory.getLogger(A05.class);

    public static void main(String[] args) throws IOException {

        // ⬇️GenericApplicationContext 是一个【干净】的容器
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("config", Config.class);
   

        // ⬇️初始化容器
        context.refresh();


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



        // ⬇️销毁容器
        context.close();

        /*
            学到了什么
                a. @ComponentScan, @Bean, @Mapper 等注解的解析属于核心容器(即 BeanFactory)的扩展功能
                b. 这些扩展功能由不同的 BeanFactory 后处理器来完成, 其实主要就是补充了一些 bean 定义
         */
    }
}

Config

package com.itheima.a05;

import com.alibaba.druid.pool.DruidDataSource;
import com.itheima.a05.mapper.Mapper1;
import com.itheima.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 标注的类相当于一个工厂
 * 里面的 @Bean 其实就充当了一个共工厂方法
 *  所以在创建的时候我们用的是工厂方法的模式来创建BeanDeification
 */

@Configuration
@ComponentScan("com.itheima.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/test");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        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;
//    }
}

下面做一些解释

当我们运行下面代码时会注册一个config的bean,但是在Config.class 类中,本身被标志为@Configuration,里面还有一些以@Bean注解注入的bean,在我们预期是不但注册了config,还要注册类中标志了@Bean的bean,下面我们运行一下如下代码打印一下BeanDefinitionName看看都有哪些bean注入进来了:
在这里插入图片描述
结果(可以发现只有config注入了进来):
在这里插入图片描述
可以得出结论,config类中的 @ComponentScan、@Bean等注解都没有生效(没解析),是谁来解析呢,就是我们要讨论的BeanFactory后处理器。

ConfigurationClassPostProcessor BeanFactory后处理器

在加上这个 ConfigurationClassPostProcessor 后处理器之后在运行一下。(这里 context.refresh();会初始化容器,,也就是加载一些我们需要的类,所以就只需将后处理器注入即可)

    context.registerBean(ConfigurationClassPostProcessor.class); // 可以解析 @ComponentScan @Bean @Import @ImportResoure

在这里插入图片描述
结果如下:(可以发现除了config、ConfigurationClassPostProcessor以外,又多了几个,这些都是我们利用注解入@Bean、@Component注入进去的):

在这里插入图片描述

MapperScannerConfigurer BeanFactory后处理器

这个是根MyBatis整合用到的一个后处理器,作用就是扫描一些mybatis的mapper接口作为BeanDefinition补充到我们的bean工厂来,在 @MapperScan底层也是这个在起作用

加上代码之后运行一下(第二个参数补充了一下扫描的包):
在这里插入图片描述
mapper 代码(记得要扫描你的mapper放的包下):

package com.itheima.a05.mapper;

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface Mapper1 {
}

结果(标记的地方是注册进去的一些Bean):
在这里插入图片描述
第一个 MapperScannerConfigurer 我们自己注入进来的吧,在后面 mapper1、mapper2 也成功注入进来了,说明我们配置的扫描mapper接口生效了,在后面五个是一些常用的后处理器,作用是解析一些注解等,具体在前面已经讲过了。

总结

  • ConfigurationClassPostProcessor 可以解析
    • @ComponentScan
    • @Bean
    • @Import
    • @ImportResource
  • MapperScannerConfigurer 可以解析
    • Mapper 接口

收获

  1. @ComponentScan, @Bean, @Mapper 等注解的解析属于核心容器(即 BeanFactory)的扩展功能
  2. 这些扩展功能由不同的 BeanFactory 后处理器来完成,其实主要就是补充了一些 bean 定义
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Aholic 冲冲冲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值