Mybaits3 source code analysis (2): Scan Mapper to associate with spring IOC container, mybaits3ioc

Source: Internet
Author: User

Mybaits3 source code analysis (2): Scan Mapper to associate with spring IOC container, mybaits3ioc

First, let's talk about how mapper is configured to an object.

<! -- Create mapper bean by means of automatic scanning (single update mode) --> <bean class = "org. mybatis. spring. mapper. mapperScannerConfigurer "> <property name =" basePackage "value =" com. xxx. dao "/> <property name =" sqlSessionTemplateBeanName "value =" sqlSessionTemplateSimple "/> <property name =" markerInterface "value =" com. xxx. dao. simpleDao "/> </bean>

All interfaces that implement classes specified by markerInterface under basePackage will be scanned and parsed. Mapperscannerproceser implements the BeanDefinitionRegistryPostProcessor (BeanDefinitionRegistry postprocessor, think about Spring AOP) interface so that it can call its postProcessBeanDefinitionRegistry method after registering all BeanDefinition in the Spring ApplicationContext container. Next, let's take a look at how MapperScannerConfigurer implements this method.

Public void postProcessBeanDefinitionRegistry (BeanDefinitionRegistry) throws BeansException {if (this. processPropertyPlaceHolders) {// process some. properties, such as sqlSessionFactoryBeanName processPropertyPlaceHolders ();} // create ClassPathMapperScanner scanner = new classpathmapperstry (registry ); // define scan rules for the rule according to the configuration. setAddToConfig (this. addToConfig); parameters. setAnnotationClass (this. annotationClass); entity. setMarkerInterface (this. markerInterface); optional. setSqlSessionFactory (this. sqlSessionFactory); parameters. setSqlSessionTemplate (this. sqlSessionTemplate); parameters. setSqlSessionFactoryBeanName (this. sqlSessionFactoryBeanName); response. setSqlSessionTemplateBeanName (this. sqlSessionTemplateBeanName); parameters. setResourceLoader (this. applicationContext); optional. setBeanNameGenerator (this. nameGenerator); alias. registerFilters (); // starts scanning. The tokenizeToStringArray function is used in the parameters to process multiple basepackages. Generally, the values are separated by commas. scan (StringUtils. tokenizeToStringArray (this. basePackage, ableableapplicationcontext. CONFIG_LOCATION_DELIMITERS ));}
The doScan function of ClassPathBeanDefinitionScanner, the parent class of the ClassPathMapperScanner class:
Protected Set <BeanDefinitionHolder> doScan (String... basePackages) {Assert. notEmpty (basePackages, "At least one base package must be specified"); // Set the container for containers in the container <strong> beanDefinitions = new javashashset <BeanDefinitionHolder> (); for (String basePackage: basePackages) {// select the candidate Set <BeanDefinition> candidates = findCandidateComponents (basePackage); for (BeanDefinition candidate: candidates) {ScopeMetadata scopeMetadata = this. scopeMetadataResolver. resolveScopeMetadata (candidate); candidate. setScope (scopeMetadata. getScopeName (); String beanName = this. beanNameGenerator. generateBeanName (candidate, this. registry); // if it is an abstract class under the base package, the ER interface we configured will handle this if (candidate instanceof AbstractBeanDefinition) {postProcessBeanDefinition (AbstractBeanDefinition) candidate, beanName);} // if the class under the base package is annotated if (candidate instanceof AnnotatedBeanDefinition) {AnnotationConfigUtils. processCommonDefinitionAnnotations (AnnotatedBeanDefinition) candidate);} // If dao package (this is the basePakage configured in general) if the class below meets the requirements of mybaits, register its BeanDefinitionif (checkCandidate (beanName, candidate) to the spring IOC container. {define definitionHolder = new BeanDefinitionHolder (candidate, beanName ); definitionHolder = AnnotationConfigUtils. applyScopedProxyMode (scopeMetadata, definitionHolder, this. registry); beanDefinitions. add (definitionHolder); registerBeanDefinition (definitionHolder, this. registry) ;}}return beanDefinitions ;}
The doScan function of classpathmapperscan:
Public Set <BeanDefinitionHolder> doScan (String... basePackages) {// call the parent class scan function 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 {for (BeanDefinitionHolder: beanDefinitions) {GenericBeanDefinition defin Ition = (GenericBeanDefinition) holder. getBeanDefinition (); // mapperInterface here is the mapper interface we write. Generally, it is an empty interface. In fact, the Bean in the BeanDefinition associated with it is MapperFactoryBean. MapperFactoryBean is very important to define ition. getPropertyValues (). add ("mapperInterface", definition. getBeanClassName (); definition. setBeanClass (MapperFactoryBean. class); definition. getPropertyValues (). add ("addToConfig", this. addToConfig); boolean explicitFactor YUsed = false; if (StringUtils. hasText (this. sqlSessionFactoryBeanName) {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 RuntimeBeanRefer Ence (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;} if (! ExplicitFactoryUsed) {if (logger. isDebugEnabled () {logger. debug ("Enabling autowire by type for MapperFactoryBean with name'" + holder. getBeanName () + "'. ");} definition. setAutowireMode (AbstractBeanDefinition. AUTOWIRE_BY_TYPE) ;}}return beanDefinitions ;}

Protected boolean checkCandidate (String beanName, BeanDefinition beanDefinition) throws IllegalStateException {// The class required by mybaits if the bean corresponding to this beanName is not registered in spring, in general, the mapper class of mybaits is an interface that will not be instantiated by spring and loaded into the IOC container if (! This. registry. containsBeanDefinition (beanName) {return true;} // If the bean of this class in spring defines BeanDefinition existingDef = this. registry. getBeanDefinition (beanName); BeanDefinition originatingDef = existingDef. getOriginatingBeanDefinition (); if (originatingDef! = Null) {existingDef = originatingDef;} // It is incompatible if you repeatedly scan this class or obtain the source files of the same class or subclass of other classes, the returned falseif (isCompatible (beanDefinition, existingDef) {return false ;} throw new ConflictingBeanDefinitionException ("Annotation-specified bean name'" + beanName + "'for bean class [" + beanDefinition. getBeanClassName () + "] conflicts with existing," + "non-compatible bean definition of same name and class [" + existingDef. getBeanClassName () + "]");}

Let's take a look at the checkDaoConfig function of MapperFactoryBean to see how it associates DAO with the corresponding mapper. xml:

Protected void checkDaoConfig () {// call the method super with the same name as the parent class. checkDaoConfig (); // obtain the Configuration of the configuration file in sqlSessionFactoryBean in java. // Add the mapper definition if there is no mapperInterface definition. // The Configuration object is in mybaits, not spring! Configuration configuration = getSqlSession (). getConfiguration (); if (this. addToConfig &&! Configuration. hasMapper (this. mapperInterface) {try {configuration. addMapper (this. mapperInterface);} catch (Throwable t) {logger. error ("Error while adding the ER er '" + this. mapperInterface + "'to configuration. ", t); throw new IllegalArgumentException (t);} finally {ErrorContext. instance (). reset ();}}}

In this way, the ER interface is registered in the sqlSession. Every time you operate the sqlSession, The mapperInterface is used to search for the corresponding Mapper. xml to construct the mapper to complete database operations.

After mybaits finds all mapper and loads it into the spring ioc container, this chapter is complete. In the next chapter, let's talk about how mybaits parses er. xml.



Zookeeper

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.