<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property> <!-- 定义别名 --> <property name="typeAliasesPackage" value="com.booway.pojo"></property> <!-- 配置映射文件的位置,如果配置文件与mapper接口在同一个位置,可以不写 --> <!-- <property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"></property> --> <!-- <property name="mapperLocations"> <array> <value>classpath:mybatis/mapper/User.xml</value> </array> </property> --> </bean> <!-- 将mybatis实现的接口注入到spring容器中 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> <property name="basePackage" value="com.booway.mapper"></property> </bean> 看下这个类的实现MapperScannerConfigurer 类申明为: public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware 这个类实现了BeanDefinitionRegistryPostProcessor,InitializingBean,ApplicationContextAware,BeanNameAware接口 实现了BeanDefinitionRegistryPostProcessor接口意味着在beanDefinition注册之后就会调用这个接口的postProcessBeanDefinitionRegistry方法。实现了InitializingBean接口意味在bean创建初始化时会调用afterPropertiesSet方法。ApplicationContextAware意味着会注入application实例,BeanNameAware意味着会注入这个bean当前的beanName 这几个接口使用的顺序为,BeanDefinitionRegistryPostProcessor,BeanNameAware,ApplicationContextAware,InitializingBean 1、先来看BeanDefinitionRegistryPostProcessor接口的实现方法 public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { if (this.processPropertyPlaceHolders) {//处理站位符 processPropertyPlaceHolders(); } ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); scanner.setAddToConfig(this.addToConfig); scanner.setAnnotationClass(this.annotationClass); scanner.setMarkerInterface(this.markerInterface); scanner.setSqlSessionFactory(this.sqlSessionFactory); scanner.setSqlSessionTemplate(this.sqlSessionTemplate); scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName); scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName); scanner.setResourceLoader(this.applicationContext); scanner.setBeanNameGenerator(this.nameGenerator); //注册过滤器,比如一些排除过滤器,注解过滤器,标记过滤器,定义一些获取类的过滤条件 scanner.registerFilters(); //扫描指定包下的类,将com.test.a,com.test,b拆分为数组 scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); } public void registerFilters() { boolean acceptAllInterfaces = true;//默认获取所有的接口作为mybatis的mapper接口 // if specified, use the given annotation and / or marker interface if (this.annotationClass != null) { //如果指定了标记的注解类型,那么就使用这个注解来标记mybatis的mapper接口 addIncludeFilter(new AnnotationTypeFilter(this.annotationClass)); acceptAllInterfaces = false; } // override AssignableTypeFilter to ignore matches on the actual marker interface //通过标记的接口来识别是不是mapper接口,只要继承了指定接口的就是,不过此处的逻辑认为继承了这个接口的就返回false,也就是不是mybatis的mapper接口 if (this.markerInterface != null) { addIncludeFilter(new AssignableTypeFilter(this.markerInterface) { @Override protected boolean matchClassName(String className) { return false; } }); acceptAllInterfaces = false; } //如果acceptAllInterfaces为true,也就是没有指定任何筛选逻辑,那么认为任何接口都返回true if (acceptAllInterfaces) { // default include filter that accepts all classes addIncludeFilter(new TypeFilter() { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { return true; } }); } //排除package-info.java // exclude package-info.java addExcludeFilter(new TypeFilter() { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { String className = metadataReader.getClassMetadata().getClassName(); return className.endsWith("package-info"); } }); } public int scan(String... basePackages) { //获取已经注册bean的个数 int beanCountAtScanStart = this.registry.getBeanDefinitionCount(); //扫描 doScan(basePackages); // Register annotation config processors, if necessary.如果包含注解配置,那么就注册注解配置处理器。 if (this.includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } //新增加的beandefinitoinCount就是mybatis扫描添加的。 return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart); } @Override public Set<BeanDefinitionHolder> doScan(String... basePackages) { Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages); if (beanDefinitions.isEmpty()) { logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration."); } else { //处理获取到的beanDefinition processBeanDefinitions(beanDefinitions); } return beanDefinitions; } protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>(); for (String basePackage : basePackages) { //获取候选组件 Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { //获取范围元数据,通过类获取这个类的scope范围还有代理模式 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); //将解析出来的scope设置到beanDefinition中 candidate.setScope(scopeMetadata.getScopeName()); //使用命名生成器生成beanName String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { //给这个beanDefinition设置默认的属性,比如默认的lazy属性啊,等等 postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { //设置注解配置的一些属性 AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } //检查候选beanDefinition类,以确定是否可以要进行注册,防止重复注册 if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; } public Set<BeanDefinition> findCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>(); try { //classpath*:com/test/a/**/*.class String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + "/" + this.resourcePattern; Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);//通过spring的PathMatchingResourcePatternResolver,获取到所有符合条件的class资源 boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) {//如果是这个资源是可读的 try { MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);//将类包装成元数据读取器,底层使用的ASM框架。 if (isCandidateComponent(metadataReader)) {//通过过滤器配置这个类是否是候选组件 ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);//这个类继承自GenericBeanDefinition sbd.setResource(resource); sbd.setSource(resource); //判断这个类是不是独立的,是不是具体的(即不是抽象或接口,可以被继承) if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { if (traceEnabled) { logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { logger.trace("Ignored because not readable: " + resource); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } return candidates; } protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { //判断当前类是否是排除的,如果是被排除,那么就不是候选的mapper 接口 for (TypeFilter tf : this.excludeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { return false; } } //判断当前类是否被包含 for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { return isConditionMatch(metadataReader); } } return false; } @Override public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) { ScopeMetadata metadata = new ScopeMetadata(); if (definition instanceof AnnotatedBeanDefinition) { AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition; AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(annDef.getMetadata(), this.scopeAnnotationType); if (attributes != null) { //获取Scope注解的value属性值 metadata.setScopeName(attributes.getAliasedString("value", this.scopeAnnotationType, definition.getSource())); //获取proxyMode属性指定的代理模式 ScopedProxyMode proxyMode = attributes.getEnum("proxyMode"); if (proxyMode == null || proxyMode == ScopedProxyMode.DEFAULT) { proxyMode = this.defaultProxyMode; } metadata.setScopedProxyMode(proxyMode); } } return metadata; } 这样就将定义的类变成了beanDefinition注册到spring中 private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) { GenericBeanDefinition definition; for (BeanDefinitionHolder holder : beanDefinitions) { definition = (GenericBeanDefinition) holder.getBeanDefinition(); if (logger.isDebugEnabled()) { logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + definition.getBeanClassName() + "' mapperInterface"); } // the mapper interface is the original class of the bean // but, the actual class of the bean is MapperFactoryBean //给这个 beanDefinition定义构造参数为自己,因为下面会定义FactoryBean definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); // issue #59 //设置工厂bean definition.setBeanClass(this.mapperFactoryBean.getClass()); //设置addToConfig属性 definition.getPropertyValues().add("addToConfig", this.addToConfig); //使用指定的工厂 boolean explicitFactoryUsed = false; if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {//如果指定了sqlSessionFactory,表示配置文件中已经配置了对应的beanName 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) { 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) { logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); } definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate); explicitFactoryUsed = true; } //如果没有指定明确的工厂bean使用,那么就设置转配模式为按类型进行装配,让spring自己到容器中找到对应bean进行装配。 if (!explicitFactoryUsed) { if (logger.isDebugEnabled()) { logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'."); } definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); } } } 那么问题来了,既然最后把所有的类的都变为了MapperFactoryBean来创造,那么这个MapperFactoryBean是怎么构造这些接口的实现类的呢? MapperFactoryBean实现了FactoryBean接口 //MapperFactoryBean的类定义 public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> { private Class<T> mapperInterface; private boolean addToConfig = true; public MapperFactoryBean() { //intentionally empty } //这个构造参数在上面的分析中已经看到,它把对应Mapper接口设置进来了 public MapperFactoryBean(Class<T> mapperInterface) { this.mapperInterface = mapperInterface; } /** * {@inheritDoc} */ @Override protected void checkDaoConfig() { super.checkDaoConfig(); notNull(this.mapperInterface, "Property 'mapperInterface' is required"); Configuration configuration = getSqlSession().getConfiguration(); if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) { try { configuration.addMapper(this.mapperInterface); } catch (Exception e) { logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", e); throw new IllegalArgumentException(e); } finally { ErrorContext.instance().reset(); } } } /** * {@inheritDoc} */ @Override public T getObject() throws Exception { return getSqlSession().getMapper(this.mapperInterface); } /** * {@inheritDoc} */ @Override public Class<T> getObjectType() { return this.mapperInterface; } /** * {@inheritDoc} */ @Override public boolean isSingleton() { return true; } //------------- mutators -------------- /** * Sets the mapper interface of the MyBatis mapper * * @param mapperInterface class of the interface */ public void setMapperInterface(Class<T> mapperInterface) { this.mapperInterface = mapperInterface; } /** * Return the mapper interface of the MyBatis mapper * * @return class of the interface */ public Class<T> getMapperInterface() { return mapperInterface; } /** * If addToConfig is false the mapper will not be added to MyBatis. This means * it must have been included in mybatis-config.xml. * <p/> * If it is true, the mapper will be added to MyBatis in the case it is not already * registered. * <p/> * By default addToCofig is true. * * @param addToConfig */ public void setAddToConfig(boolean addToConfig) { this.addToConfig = addToConfig; } /** * Return the flag for addition into MyBatis config. * * @return true if the mapper will be added to MyBatis in the case it is not already * registered. */ public boolean isAddToConfig() { return addToConfig; } } //底层就是使用的mybatis获取接口实现的方法。 public T getObject() throws Exception { return getSqlSession().getMapper(this.mapperInterface); }