The Mapper will Mybatis registered to Spring's ApplicationContext in a Spring life cycle management.
Mapper scanned for annotations usage
@Configuration
@MapperScan("org.mybatis.spring.sample.mapper")
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(MapperScannerRegistrar.class) public @interface MapperScan
Here, it is noted @MapperScan which wraps a comment: @Import (MapperScannerRegistrar.class)
Link @Import treatment: 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 parsing and BeanDefiniton registration link: ConfigurationClassPostProcessor.processConfigBeanDefinitions
/** * Build and validate a configuration model based on the registry of * {@link Configuration} classes. */ public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>(); //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)); } } ............ the Set <BeanDefinitionHolder> a LinkedHashSet candidates in a new new = <BeanDefinitionHolder> (configCandidates); do { //. 3, which renders all classes @Configuration all annotations (@ Bean, @ Profile, Import @, ImportResource @, @ ComponentScan, Lazy @, @ PropertySource) parser.parse (candidates in a); ............
the Set <ConfigurationClass> = new new configClasses a LinkedHashSet <ConfigurationClass> (parser.getConfigurationClasses ( )); ............ // 4, by which resolution configClasses, all arranged converted to the BeanDefinition this.reader.loadBeanDefinitions (configClasses); ......... ... } the while (candidates.isEmpty ()!); ............ }
Here we look at what things do MapperScannerRegistrar
registerBeanDefinitions: Registration 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<String> basePackages = new ArrayList<String>(); 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")) { // set basePackages basePackages.add (ClassUtils.getPackageName (clazz)); } // The annotationClass and markerInterface, provided addIncludeFilter scanner.registerFilters () ; // start scanning scanner.doScan (StringUtils.toStringArray (basePackages)); }
scanner.doScan: Scan
@Override public the Set <BeanDefinitionHolder> the doScan (String basePackages ...) { // call ClassPathBeanDefinitionScanner.doScan, all classes are registered under the package into a container the Set <BeanDefinitionHolder> BeanDefinitions = super.doScan (basePackages); IF (BeanDefinitions .isEmpty ()) { logger.warn ( "No MyBatis Mapper WAS found in '" + of Arrays.toString (basePackages) + "' Please Check your Package Configuration.."); } the else { // to beanDefinitions information 1, these interfaces allow the dynamic proxy classes MapperFactoryBean 2 may be provided corresponding to the proxy object SqlSession in processBeanDefinitions (BeanDefinitions); } return BeanDefinitions; }
processBeanDefinitions: processing BeanDefiniton
void processBeanDefinitions Private (the Set <BeanDefinitionHolder> BeanDefinitions) { GenericBeanDefinition Definition; for: (BeanDefinitionHolder Holder BeanDefinitions) { holder.getBeanDefinition Definition = (GenericBeanDefinition) (); ........... // The interface IS Mapper the class of the bean Original the // But, the Actual the class of the bean MapperFactoryBean iS // constructor is provided as the interface into the parameters, see later MapperFactoryBean constructor, which is able to understand why in the definition.getConstructorArgumentValues (). addGenericArgumentValue (definition.getBeanClassName ()); // Issue # 59 // Mapper will MapperFactoryBean.class as a class, is to make Sprintg perception, the Bean instance is to be created by defining the FactoryBean definition.setBeanClass (the this. mapperFactoryBean.getClass ()); ........... // set to run when the bean reference sqlSessionFactoryBeanName (sqlSessionFactoryRef value) is definition.getPropertyValues () the Add ( "SqlSessionFactory", new new RuntimeBeanReference (this.sqlSessionFactoryBeanName));. // set sqlSessionTemplateBeanName bean reference (value of sqlSessionTemplateRef) runtime definition.getPropertyValues () the Add ( "SqlSessionTemplate", new new RuntimeBeanReference (this.sqlSessionTemplateBeanName));. ........... } }