聊聊、手写Mybatis 注解配置方式

GechangLiu 2020-04-08

导航:  

聊聊、Mybatis API  

聊聊、Mybatis XML 

聊聊、Mybatis集成Spring XML 方式

聊聊、Mybatis集成Spring 注解方式

聊聊、手写Mybatis XML配置方式

在《聊聊、手写Mybatis XML配置方式》中聊了通过 XML配置方式 来实现 Mybatis,也聊到了 Mybatis 中用到的动态代理技术。我手动实现了 AccountMapperFactoryBean,但是有一个缺点,需要 XML 配置才可以用。类似 MapperFactoryBean。

这篇文章主要是聊聊通过注解方式来手写 Mybatis。我们向 Spring 注册 Bean 的方式有很多种,这里会用到 ImportBeanDefinitionRegistrar,它就是今天的主角。

自定义 AccountImportBeanDefinitionRegistrar  实现 ImportBeanDefinitionRegistrar 

AccountImportBeanDefinitionRegistrar   


package org.rockcode.factory;


import org.rockcode.mappers.AccountMapper;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

public class AccountImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
  BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(AccountMapperFactoryBean.class);
  AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
  beanDefinition.getPropertyValues().add("mapperInterface", AccountMapper.class);
  beanDefinitionRegistry.registerBeanDefinition("accountMapperFactoryBean",beanDefinition);
}
}

AccountConfig 


package org.rockcode.config; 

import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.rockcode.factory.AccountImportBeanDefinitionRegistrar;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

import javax.sql.DataSource; 

@Configuration
@Import(AccountImportBeanDefinitionRegistrar.class)
public class AccountConfig {

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

@Bean
public DataSource dataSource(){
DruidDataSource driverManagerDataSource = new DruidDataSource();
driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
driverManagerDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test?useSSL=false");
driverManagerDataSource.setUsername("root");
driverManagerDataSource.setPassword("root");
return driverManagerDataSource;
} 

}

AccountMapperFactoryBean 


package org.rockcode.factory;


import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import static org.springframework.util.Assert.notNull;

public class AccountMapperFactoryBean extends SqlSessionDaoSupport implements FactoryBean {

private Class mapperInterface;

public void setMapperInterface(Class mapperInterface) {
this.mapperInterface = mapperInterface;
}

@Autowired
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
super.setSqlSessionFactory(sqlSessionFactory);
}

@Override
protected void checkDaoConfig() {
super.checkDaoConfig();
notNull(this.mapperInterface, "Property ‘mapperInterface‘ is required");
Configuration configuration = getSqlSession().getConfiguration();
configuration.addMapper(this.mapperInterface);
}

@Override
public Object getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}

@Override
public Class<?> getObjectType() {
return this.mapperInterface;
}
}  

Main方法 


package org.rockcode.config; 

import org.rockcode.mappers.AccountMapper;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
public static void main(String[] args) {
  AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AccountConfig.class);
  AccountMapper accountMapper = (AccountMapper) ac.getBean("accountMapperFactoryBean");
  System.out.println(accountMapper.queryAll());
}
} 

上面代码的重点在于  @Import(AccountImportBeanDefinitionRegistrar.class),这是 Spring 很重要的一个扩展点,与 ImportBeanDefinitionRegistrar 相同的扩展点还有 ImportSelector,它们都可以实现 Bean 的注册。 

相关推荐