Mybatis-Spring(1)BeanDefinition
将Mybatis中的Mapper注册到Spring的ApplicationContext中,受Spring的生命周期管理。
Mapper扫描注解,用法
@Configuration
@MapperScan("org.mybatis.spring.sample.mapper")
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(MapperScannerRegistrar.class) public @interface MapperScan
这里,注意到@MapperScan其中包装了一个注解:@Import(MapperScannerRegistrar.class)
@Import处理的环节:AbstractApplicationContext.refresh()
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
............
try {
............
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
............
}
}
}
@Import解析并且将BeanDefiniton注册环节:ConfigurationClassPostProcessor.processConfigBeanDefinitions
/**
* Build and validate a configuration model based on the registry of
* {@link Configuration} classes.
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List configCandidates = new ArrayList();
//1、所有的BeanDefiniton的name
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
............
//2、将所有的@Configuration的类放入configCandidates中
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
............
Set candidates = new LinkedHashSet(configCandidates);
do {
//3、解析所有的@Configuration类里面所有的注解(@Bean、@Profile、@Import、@ImportResource、@ComponentScan、@Lazy、@PropertySource)
parser.parse(candidates);
............
Set configClasses = new LinkedHashSet(parser.getConfigurationClasses());
............
//4、通过解析成的configClasses,将所有的配置转化成BeanDefinition
this.reader.loadBeanDefinitions(configClasses);
............
}
while (!candidates.isEmpty());
............
}
下面我们看下MapperScannerRegistrar做了哪些事情
registerBeanDefinitions:注册Bean
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// MapperScan配置的注解数据
AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
if (!Annotation.class.equals(annotationClass)) {
// 设置需要注册的annotationClass
scanner.setAnnotationClass(annotationClass);
}
Class<?> markerInterface = annoAttrs.getClass("markerInterface");
if (!Class.class.equals(markerInterface)) {
// 设置需要注册的markerInterface
scanner.setMarkerInterface(markerInterface);
}
Class<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator");
if (!BeanNameGenerator.class.equals(generatorClass)) {
// 设置自定义的BeanNameGenerator
scanner.setBeanNameGenerator(BeanUtils.instantiateClass(generatorClass));
}
Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
// 设置自定义的MapperFactoryBean.class
scanner.setMapperFactoryBean(BeanUtils.instantiateClass(mapperFactoryBeanClass));
}
// 设置sqlSessionTemplateRef的值到sqlSessionTemplateBeanName
scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
// 设置sqlSessionTemplateRef的值到sqlSessionFactoryBeanName
scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));
List basePackages = new ArrayList();
for (String pkg : annoAttrs.getStringArray("value")) {
if (StringUtils.hasText(pkg)) {
// 设置basePackages
basePackages.add(pkg);
}
}
for (String pkg : annoAttrs.getStringArray("basePackages")) {
if (StringUtils.hasText(pkg)) {
// 设置basePackages
basePackages.add(pkg);
}
}
for (Class<?> clazz : annoAttrs.getClassArray("basePackageClasses")) {
// 设置basePackages
basePackages.add(ClassUtils.getPackageName(clazz));
}
// 根据annotationClass和markerInterface,设置addIncludeFilter
scanner.registerFilters();
// 开始扫描
scanner.doScan(StringUtils.toStringArray(basePackages));
}
scanner.doScan:扫描
@Override public SetdoScan(String... basePackages) { // 调用ClassPathBeanDefinitionScanner.doScan,将包下所有的类都注册到容器中 Set beanDefinitions = super.doScan(basePackages); if (beanDefinitions.isEmpty()) { logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration."); } else { // 为了beanDefinitions信息,1、让这些接口类可以被MapperFactoryBean动态代理 2、设置对应的SqlSession到被代理的对象中 processBeanDefinitions(beanDefinitions); } return beanDefinitions; }
processBeanDefinitions:处理BeanDefiniton
private void processBeanDefinitions(SetbeanDefinitions) { GenericBeanDefinition definition; for (BeanDefinitionHolder holder : beanDefinitions) { definition = (GenericBeanDefinition) holder.getBeanDefinition(); ........... // the mapper interface is the original class of the bean // but, the actual class of the bean is MapperFactoryBean // 设置接口作为构造器入参,后面看MapperFactoryBean的构造器,就能理解这是干嘛的了 definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); // issue #59 // 将MapperFactoryBean.class作为Mapper的类,是为了让Sprintg感知,这个Bean的实例是要通过定义的FactoryBean来创建的 definition.setBeanClass(this.mapperFactoryBean.getClass()); ........... // 设置sqlSessionFactoryBeanName(sqlSessionFactoryRef的值)的运行时bean引用 definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName)); // 设置sqlSessionTemplateBeanName(sqlSessionTemplateRef的值)的运行时bean引用 definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName)); ........... } }