Mybatis mapperscannerconfigurer Auto-scan injects mapper interface generation agent into spring
MyBatis can configure Mapperfactorybean to generate proxies for mapper interfaces when integrated with spring. For example
class= "Org.mybatis.spring.mapper.MapperFactoryBean" > <property name= "Mapperinterface" value= " Org.mybatis.spring.sample.mapper.UserMapper "/> <property name=" sqlsessionfactory "ref=" Sqlsessionfactory "/></bean>
The proxy class created by Mapperfactorybean implements the Usermapper interface and injects it into the application. Because the agent is created in the runtime environment (runtime, translator note), the specified mapper must be an interface, not a specific implementation class.
The above configuration has a big disadvantage, is that the system has a lot of configuration files need to be written manually, so the above way is very useful.
It is not necessary to register all the mappers in the Spring XML configuration file. Instead, you can use a mapperscannerconfigurer, which will look for mappers under the classpath and automatically build them into Mapperfactorybean.
To create a mapperscannerconfigurer, you can add the following code to the Spring configuration:
class= "Org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name= "Basepackage" value = "Org.mybatis.spring.sample.mapper"/></bean>
The Basepackage property lets you set the basic package path for the Mapper interface file. You can use a semicolon or comma as a delimiter to set more than one package path. Each mapper will be recursively searched in the specified package path.
Note that it is not necessary to specify Sqlsessionfactory or Sqlsessiontemplate, because Mapperscannerconfigurer will create Mapperfactorybean and then assemble automatically. However, if you use more than one DataSource, automatic assembly may fail. In this case, you can use the Sqlsessionfactorybeanname or Sqlsessiontemplatebeanname property to set the correct bean name. This is how it is configured, note that the bean name is required, not the bean's reference, and therefore the Value property replaces the usual ref:
<property name= "Sqlsessionfactorybeanname" value= "Sqlsessionfactory"/>
Mapperscannerconfigurer supports filtering by creating a mapper from the specified creation interface or annotations. The Annotationclass property specifies the name of the note to look for. The Markerinterface property specifies the parent interface to look for. If both are specified, the mapper added to the interface will match the two criteria. By default, both properties are null, so all interfaces given in the base package can be loaded as mappers.
The discovered mapper will use spring to name the auto-detect component (refer to the Spring Manual's 3.14.4) default naming policy. That is, if no annotations are found, it uses the non-uppercase, non-fully qualified class name of the mapper. However, if a @named annotation of @component or JSR-330 is found, it gets the name. Note that you can configure to Org.springframework.stereotype.Component, javax.inject.Named (if you use JSE 6) or your own annotations (which are definitely self-explanatory), which The sample annotations will be used as generators and name providers.
Next, let's look at the source code of the Mapperscannerconfigurer class to see how it is automatically scanned.
public void Postprocessbeandefinitionregistry (Beandefinitionregistry registry) throws Beansexception {2 if (This.proc Esspropertyplaceholders) {3 processpropertyplaceholders (); 4} 5 6 Classpathmapperscanner scanner = new Cl Asspathmapperscanner (registry); 7 Scanner.setaddtoconfig (This.addtoconfig); 8 Scanner.setannotationclass (This.annotationclass); 9 Scanner.setmarkerinterface (This.markerinterface); scanner.setsqlsessionfactory (this.sqlsessionfactory); 11 Scanner.setsqlsessiontemplate (this.sqlsessiontemplate); Scanner.setsqlsessionfactorybeanname ( This.sqlsessionfactorybeanname); Scanner.setsqlsessiontemplatebeanname (this.sqlsessiontemplatebeanname); 14 Scanner.setresourceloader (This.applicationcontext); Scanner.setbeannamegenerator (this.nameGenerator); 16 Scanner.registerfilters (); Scanner.scan (Stringutils.tokenizetostringarray (This.basepackage, Configurableapplicationcontext.config_location_delimiters)); 18} put the mapPer interface converted to Mapperfactorybean code in the 17 line this method, let's follow it in to look. 1 @Override 2 public set<beandefinitionholder> doscan (String ... basepackages) {3 Set<beandefinitionholde r> beandefinitions = Super.doscan (basepackages); 4 5 if (Beandefinitions.isempty ()) {6 Logger.warn ("No MyBatis Mapper is found in '" + arrays.tostring (Basepac kages) + "' package. Please check your configuration. "); 7} else {8 for (Beandefinitionholder holder:beandefinitions) {9 Genericbeandefinition definition = (genericbeandefinition) holder.getbeandefinition (), if (logger.isdebugenabled ()) {Logger.debug (" Creating Mapperfactorybean with Name ' "+ holder.getbeanname () +" ' and ' "+ definition.getbeanclassname ( ) + "' Mapperinterface");}15//The Mapper interface is the original class of the BEAN17// But, the actual class of the beans is MapperFactoryBean18//the type of interface is set into Definition.getpropErtyvalues (). Add ("Mapperinterface", Definition.getbeanclassname ()); 20//Set the True type of bean Mapperfactorybean de Finition.setbeanclass (Mapperfactorybean.class), 22//Whether the Mapper interface is added to the MyBatis config to the Definition.getproper Tyvalues (). Add ("Addtoconfig", This.addtoconfig); Boolean explicitfactoryused = false;26//If Sqlsessio Nfactorybeanname name is not empty query in spring container 27//suitable for multiple data source (Stringutils.hastext (This.sqlsessionfactorybeanname)) {definition.getpropertyvalues (). Add ("Sqlsessionfactory", New Runtimebeanreference (This.sqlsessionfactorybean Name); explicitfactoryused = true;31} else if (this.sqlsessionfactory! = null) {Definit Ion.getpropertyvalues (). Add ("Sqlsessionfactory", this.sqlsessionfactory); explicitfactoryused = true;34 }35 36//If Sqlsessiontemplatebeanname's name is not empty then query in the Spring container 37//For multi-data source if (stringutils.ha39 if (stringutils.hastExt (this.sqlsessiontemplatebeanname)) {explicitfactoryused) {Logger.warn ("Cannot use both: Sqlsessiontemplate and Sqlsessionfactory together. Sqlsessionfactory is ignored. "); }43 definition.getpropertyvalues (). Add ("Sqlsessiontemplate", New Runtimebeanreference (This.sqlsessi Ontemplatebeanname)); explicitfactoryused = true;45} else if (this.sqlsessiontemplate! = null) {46 if (explicitfactoryused) {Logger.warn ("Cannot use both:sqlsessiontemplate and sqlsessionfactory to Gether. Sqlsessionfactory is ignored. "); }49 definition.getpropertyvalues (). Add ("Sqlsessiontemplate", this.sqlsessiontemplate); 50 explicitfactoryused = true;51}52 if (!explicitfactoryused) {si if (logger.isdebugenabled ()) {Logger.debug ("Enabling Autowire by type for Mapperfactorybean with Name '" + holder.getbeanname () + "'.") ; 56}57 Definition.setautowiremode (Abstractbeandefinition.autowire_by_type); 58}59}60}61//This set returns after S The Pring container will register all contents inside the container and return beandefinitions;63}
MyBatis below the Mapperscannerconfigurer scanner