package org.mybatis.spring.mapper;import java.io.IOException;import java.lang.annotation.Annotation;import java.util.Arrays;import java.util.Set;import org.apache.commons.logging.Log;import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.SqlSessionTemplate;import org.springframework.beans.MutablePropertyValues;import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;import org.springframework.beans.factory.config.BeanDefinition;import org.springframework.beans.factory.config.BeanDefinitionHolder;import org.springframework.beans.factory.config.RuntimeBeanReference;import org.springframework.beans.factory.support.BeanDefinitionRegistry;import org.springframework.beans.factory.support.GenericBeanDefinition;import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;import org.springframework.core.type.AnnotationMetadata;import org.springframework.core.type.ClassMetadata;import org.springframework.core.type.classreading.MetadataReader;import org.springframework.core.type.classreading.MetadataReaderFactory;import org.springframework.core.type.filter.AnnotationTypeFilter;import org.springframework.core.type.filter.AssignableTypeFilter;import org.springframework.core.type.filter.TypeFilter;import org.springframework.util.StringUtils;public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner{ private boolean addToConfig = true; private SqlSessionFactory sqlSessionFactory; private SqlSessionTemplate sqlSessionTemplate; private String sqlSessionTemplateBeanName; private String sqlSessionFactoryBeanName; private Class annotationClass; private Class markerInterface; public ClassPathMapperScanner(BeanDefinitionRegistry registry) { super(registry, false); } public void setAddToConfig(boolean addToConfig) { this.addToConfig = addToConfig; } public void setAnnotationClass(Class annotationClass) { this.annotationClass = annotationClass; } public void setMarkerInterface(Class markerInterface) { this.markerInterface = markerInterface; } public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; } public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { this.sqlSessionTemplate = sqlSessionTemplate; } public void setSqlSessionTemplateBeanName(String sqlSessionTemplateBeanName) { this.sqlSessionTemplateBeanName = sqlSessionTemplateBeanName; } public void setSqlSessionFactoryBeanName(String sqlSessionFactoryBeanName) { this.sqlSessionFactoryBeanName = sqlSessionFactoryBeanName; } public void registerFilters() { boolean acceptAllInterfaces = true; if (this.annotationClass != null) { addIncludeFilter(new AnnotationTypeFilter(this.annotationClass)); acceptAllInterfaces = false; } if (this.markerInterface != null) { addIncludeFilter(new AssignableTypeFilter(this.markerInterface) { protected boolean matchClassName(String className) { return false; } }); acceptAllInterfaces = false; } if (acceptAllInterfaces) { addIncludeFilter(new TypeFilter() { public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { return true; } }); } addExcludeFilter(new TypeFilter() { public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { String className = metadataReader.getClassMetadata().getClassName(); return className.endsWith("package-info"); } }); } // 对某个包下的所有类 扫描通过 spring BeanDefinitionHolder 对接口进行 内部属性操作 public SetdoScan(String... basePackages) { Set beanDefinitions = super.doScan(basePackages); if (beanDefinitions.isEmpty()) { this.logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration."); } else { for (BeanDefinitionHolder holder : beanDefinitions) { GenericBeanDefinition definition = (GenericBeanDefinition)holder.getBeanDefinition(); if (this.logger.isDebugEnabled()) { this.logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + definition.getBeanClassName() + "' mapperInterface"); } //添加自己在 mybatis mapper 中 对应的mapper key definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName()); //设置bean 的 class 为 MapperFactoryBean definition.setBeanClass(MapperFactoryBean.class); //是否添加到 配置中心 definition.getPropertyValues().add("addToConfig", Boolean.valueOf(this.addToConfig)); boolean explicitFactoryUsed = false; if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) { //添加 sqlSessionFactory用于获取 数据库连接 definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionFactory != null) { definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory); explicitFactoryUsed = true; } if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) { if (explicitFactoryUsed) { this.logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); } definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionTemplate != null) { if (explicitFactoryUsed) { this.logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); } definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate); explicitFactoryUsed = true; } if (!explicitFactoryUsed) { if (this.logger.isDebugEnabled()) { this.logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'."); } definition.setAutowireMode(2); } } } return beanDefinitions; } protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { return (beanDefinition.getMetadata().isInterface()) && (beanDefinition.getMetadata().isIndependent()); } protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException { if (super.checkCandidate(beanName, beanDefinition)) { return true; } this.logger.warn("Skipping MapperFactoryBean with name '" + beanName + "' and '" + beanDefinition.getBeanClassName() + "' mapperInterface" + ". Bean already defined with the same name!"); return false; }}