<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); }