Spring-Mybatis 中的接口为什么可以注入原理 (BeanPostProcessor 后置处理器)

Spring-Mybatis 中的接口为什么可以注入原理 (BeanPostProcessor 后置处理器)_第1张图片

 

 

Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口(也就是本文用的dao层下面的BookMapper)生成代理注入到Spring

 

原理是

Mybatis在与Spring集成的时候可以配置MapperFactoryBean来生成Mapper接口的代理. 例如

 /**
     * dataSource.
     */
    @Bean(name = "dataSource")
    public BasicDataSource dataSource() {
        BasicDataSource dataSource = loadSource();
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    private BasicDataSource loadSource() {
        BasicDataSource dataSourceJira = new BasicDataSource();
        dataSourceJira.setDriverClassName(classname);
        dataSourceJira.setInitialSize(datasourceInitialsize);
        dataSourceJira.setMaxActive(datasourceMaxActive);
        dataSourceJira.setMaxIdle(datasourceMaxIdle);
        dataSourceJira.setMinIdle(datasourceMinIdle);
        dataSourceJira.setMaxWait(datasourceMaxWait);
        dataSourceJira.setMinEvictableIdleTimeMillis(datasourceMinEvicTimemillis);
        dataSourceJira.setTimeBetweenEvictionRunsMillis(datasourceTimeBetweenEvicRunMillis);
        dataSourceJira.setRemoveAbandoned(datasourceRemoveAbandoned);
        dataSourceJira.setRemoveAbandonedTimeout(datasourceRemoveAbandonedTimeout);
        dataSourceJira.setLogAbandoned(datasourceLogAbandoned);
        dataSourceJira.setTestOnBorrow(datasourceTestOnBorrow);
        dataSourceJira.setTestOnReturn(datasourceTestOnReturn);
        dataSourceJira.setTestWhileIdle(datasourceTestwhileIdle);
        dataSourceJira.setValidationQueryTimeout(600);
        return dataSourceJira;
    }

    /**
    sqlSessionFactoryBean
     */
    @Bean(name = "sqlSessionFactoryName")
    @ConditionalOnMissingBean // 当容器里没有指定的Bean的情况下创建该对象
    public SqlSessionFactoryBean sqlSessionFactoryBean(
            @Qualifier("dataSource") BasicDataSource  dataSource) {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        // 设置数据源
        sqlSessionFactoryBean.setDataSource(multipleDataSource);
        // 设置mybatis的主配置文件
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource mybatisConfigXml = resolver.getResource("classpath:spring/sqlmap-config.xml");
        sqlSessionFactoryBean.setConfigLocation(mybatisConfigXml);
        return sqlSessionFactoryBean;
    }
    
    /**
     * mapper接口的扫描器.
     * @return mapperScannerConfigurer.
     */
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactoryName");
        mapperScannerConfigurer.setBasePackage("com.davinqi.**.mapper");
        return mapperScannerConfigurer;
    }

Mybatis 创建了  MapperFactoryBean 的代理类实现了  .mapper 接口,并且注入到springBean容器中 。 

Spring-Mybatis 中的接口为什么可以注入原理 (BeanPostProcessor 后置处理器)_第2张图片

 

Spring-Mybatis 中的接口为什么可以注入原理 (BeanPostProcessor 后置处理器)_第3张图片

 

public abstract class SqlSessionDaoSupport extends DaoSupport {
    private SqlSession sqlSession;
    private boolean externalSqlSession;

    public SqlSessionDaoSupport() {
    }

    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        if (!this.externalSqlSession) {
            this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
        }

    }

    public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
        this.sqlSession = sqlSessionTemplate;
        this.externalSqlSession = true;
    }

    public SqlSession getSqlSession() {
        return this.sqlSession;
    }

    protected void checkDaoConfig() {
        Assert.notNull(this.sqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
    }
}

 

 public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
        Assert.notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
        Assert.notNull(executorType, "Property 'executorType' is required");
        this.sqlSessionFactory = sqlSessionFactory;
        this.executorType = executorType;
        this.exceptionTranslator = exceptionTranslator;
        this.sqlSessionProxy = (SqlSession)Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionTemplate.SqlSessionInterceptor());
    }

 

看到这: Proxy.newProxyInstance 

大家应该都懂了,他就是使用的Jdk的动态代理。 

 

MyBatis-Spring提供了一个MapperFactoryBean,可以将数据映射接口转为Spring Bean。果数据映射接口很多的话,需要在Spring的配置文件中对数据映射接口做配置,相应的配置项会很多了。

在Service中@Autowired的方法直接注入接口实例。在Spring的配置文件中可以采用以下所示的配置将接口转化为Bean。为了简化配置,在MyBatis-Spring中提供了一个转换器MapperScannerConfig它 继承了 Spring 的 BeanPostProcessor 后置处理器 这样在spring

容器启动时就可以加载Mybatis自动反射实现的类到容器中的Bean了。

你可能感兴趣的:(Spring,mybatis,mybatis,spring,spring,boot,ioc)