Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to integrate Mybatis Analysis for automatic configuration through SpringBoot

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

In this issue, the editor will bring you about how to integrate Mybatis analysis automatic configuration through SpringBoot. The article is rich in content and analyzes and describes for you from a professional point of view. I hope you can get something after reading this article.

Preface

With the concept of "convention is greater than configuration", SpringBoot has become the most popular web development framework, so it is necessary to have an in-depth understanding of it. In this paper, we analyze the automatic configuration (AutoConfigure) function provided by SpringBoot by integrating Mybatis classes, and first look at an example of integrating Mybatis.

SpringBoot integrates Mybatis

Provide an example of SpringBoot integrating Mybatis, and realize simple functions of adding, deleting, modifying and querying through Mybatis.

1. Table data

CREATE TABLE `role` (`note` varchar (255) CHARACTER SET utf8 DEFAULT NULL, `role_ name` varchar (255) DEFAULT NULL, `id` bigint (20) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8

Provide sql related to the creation of role table, add, delete, modify and query the table

two。 Integration of Mybatis dependencies

Mainly mybatis-spring-boot-starter and mysql drivers used:

Org.mybatis.spring.boot mybatis-spring-boot-starter 2.0.1 mysql mysql-connector-java 5.1.29

3. Configure application.properties

Provide information about connecting to mysql: url, driver, user name, password

Spring.datasource.url=jdbc:mysql://localhost/mybatisspring.datasource.username=rootspring.datasource.password=rootspring.datasource.driver-class-name=com.mysql.jdbc.Driver

4. Provide bean and Dao

Provide the bean class corresponding to the table and the dao class that operates the database, respectively.

Public class Role {private long id; private String roleName; private String note; / / omit get/set method}

@ Mapperpublic interface RoleDao {@ Select ("SELECT id,role_name as roleName,note FROM role WHERE id = # {id}") Role findRoleById (@ Param ("id") long id);}

5. Provide Service and Controller

Public interface RoleService {public Role findRoleById (long roleId);} @ Servicepublic class RoleServiceImpl implements RoleService {@ Autowired private RoleDao roleDao; @ Override public Role findRoleById (long roleId) {return roleDao.findRoleById (roleId);}}

RestControllerpublic class RoleController {@ Autowired private RoleService roleService; @ RequestMapping ("/ role") public String getRole (long id) {return roleService.findRoleById (id) .toString ();}}

Start the service and do a simple test: http://localhost:8888/role?id=111

The results are as follows:

Role [id=111, roleName=zhaohui, note=hello]

6. Ask questions

As in the example above, we use very little configuration to manipulate the database through mybatis. The SqlSessionFactory and SqlSession required for normal use of mybatis are not instantiated, and the data sources that mybatis depends on are not seen to be referenced. How does SpringBoot help us configure automatically? let's focus on the analysis below.

SpringBoot automatic configuration

1. Automatic configuration annotation

To use the autoconfiguration feature, SpringBoot provides the annotation @ EnableAutoConfiguration, which of course does not require our configuration because it is default and enabled in the @ SpringBootApplication annotation

Target (ElementType.TYPE) @ Retention (RetentionPolicy.RUNTIME) @ Documented@Inherited@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan (excludeFilters = {@ Filter (type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @ Filter (type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)}) public @ interface SpringBootApplication {/ /. Omit.}

You can see that the @ SpringBootApplication annotation itself also has the annotation @ EnableAutoConfiguration:

Target (ElementType.TYPE) @ Retention (RetentionPolicy.RUNTIME) @ Documented@Inherited@AutoConfigurationPackage@Import (AutoConfigurationImportSelector.class) public @ interface EnableAutoConfiguration {/ /. Omit.}

In the annotation @ EnableAutoConfiguration, take a look at the AutoConfigurationImportSelector class used in the @ Import annotation. This class is the core class of automatic annotation, and the configuration class we specify by default will be loaded conditionally. Here are two concepts, one is conditional, the other is configuration class, which can be briefly introduced: configuration class can be simply understood as the docking class of SpringBoot for related components, which can do some initialization work. Conditional means that it is not possible to be docked with configuration classes. SpringBoot provides a large number of configuration classes by default, but not all configuration classes can be loaded and initialized. For example, mybatis cannot be docked without data sources and without mybatis basic package. Let's take a look at which conditional classes SpringBoot provides.

two。 Conditional class

SpringBoot provides many condition classes, which can be configured in the configuration. The related condition classes can be found under org.springframework.boot.autoconfigure.condition under the spring-boot-autoconfigure package, including the following:

ConditionalOnBean: current container with specified Bean; ConditionalOnClass: specified class under the current classpath; ConditionalOnCloudPlatform: when cloud platform is specified; ConditionalOnExpression:SpEL expression as judgment condition; ConditionalOnJava:JVM version as judgment condition; ConditionalOnJndi: to find the specified location under the condition of JNDI existence; ConditionalOnMissingBean: when no Bean is specified in the container; ConditionalOnMissingClass: when no class is specified in the classpath ConditionalOnNotWebApplication: under the condition that the current project is not a WEB project; ConditionalOnProperty: whether the current application is configured with the value specified by the specified attribute; ConditionalOnResource: only if the specified resource is under the classpath; the main candidate bean; ConditionalOnWebApplication is only one or more cases in the ConditionalOnSingleCandidate:bean factory: the current project is a WEB project.

The above is the annotation class. The annotation itself has no function, but only provides the tag function. The specific function is specified in @ Conditional, such as the ConditionalOnBean annotation as shown below:

Target ({ElementType.TYPE, ElementType.METHOD}) @ Retention (RetentionPolicy.RUNTIME) @ Documented@Conditional (OnBeanCondition.class) public @ interface ConditionalOnBean {/ / Omit.}

The implementation of related functions is found in the OnBeanCondition class, and the implementation classes of other annotation classes are also found in the package org.springframework.boot.autoconfigure.condition.

3. Automatic configuration process

During the startup of the Springboot application, ConfigurationClassParser is used to analyze the configuration class. There is a processImports method in this class. This method is used to deal with @ Import annotation. @ Import annotation exists in @ EnableAutoConfiguration annotation, and AutoConfigurationImportSelector in the annotation is instantiated. There is an AutoConfigurationGroup inner class inside it. The inner class has two core methods: process and selectImports.

@ Override public void process (AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {Assert.state (deferredImportSelector instanceof AutoConfigurationImportSelector, ()-> String.format ("Only% s implementations are supported, got% s", AutoConfigurationImportSelector.class.getSimpleName (), deferredImportSelector.getClass () .getName (); AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector) .getAutoConfigurationEntry (getAutoConfigurationMetadata (), annotationMetadata); this.autoConfigurationEntries.add (autoConfigurationEntry); for (String importClassName: autoConfigurationEntry.getConfigurations ()) {this.entries.putIfAbsent (importClassName, annotationMetadata);}}

This method mainly obtains the automatic configuration classes that are available after conditional filtering, which is mainly accomplished by calling getAutoConfigurationEntry in AutoConfigurationImportSelector:

Protected AutoConfigurationEntry getAutoConfigurationEntry (AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {if (! isEnabled (annotationMetadata)) {return EMPTY_ENTRY;} AnnotationAttributes attributes = getAttributes (annotationMetadata); List configurations = getCandidateConfigurations (annotationMetadata, attributes); configurations = removeDuplicates (configurations); Set exclusions = getExclusions (annotationMetadata, attributes); checkExcludedClasses (configurations, exclusions); configurations.removeAll (exclusions); configurations = filter (configurations, autoConfigurationMetadata); fireAutoConfigurationImportEvents (configurations, exclusions); return new AutoConfigurationEntry (configurations, exclusions);}

First, all the alternative automatic configuration classes are obtained, then the duplicate and excluded classes are deleted, and finally, the available configuration classes are filtered by criteria. Let's take a look at each of them. First, let's take a look at how to get all the alternative configuration classes:

Protected List getCandidateConfigurations (AnnotationMetadata metadata, AnnotationAttributes attributes) {List configurations = SpringFactoriesLoader.loadFactoryNames (getSpringFactoriesLoaderFactoryClass (), getBeanClassLoader ()); Assert.notEmpty (configurations, "No auto configuration classes found in META-INF/spring.factories. If you" + "are using a custom packaging, make sure that file is correct."); return configurations;}

Use SpringFactoriesLoader to obtain the configuration class whose key is org.springframework.boot.autoconfigure.EnableAutoConfiguration in the META-INF/spring.factories file under the classpath. You can take a look at the spring.factories content in spring-boot-autoconfigure.jar:

# Auto Configureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\ / /. The following is omitted.

Of course, it only intercepts part of the configuration under one of the classpath jar, gets all the configuration classes, removes the duplicates, removes the excluded classes, and then performs conditional filtering. Let's take a look at the following:

Private List filter (List configurations, AutoConfigurationMetadata autoConfigurationMetadata) {long startTime = System.nanoTime (); String [] candidates = StringUtils.toStringArray (configurations); boolean [] skip = new boolean [candidates.length]; boolean skipped = false; for (AutoConfigurationImportFilter filter: getAutoConfigurationImportFilters ()) {invokeAwareMethods (filter); boolean [] match = filter.match (candidates, autoConfigurationMetadata); for (int I = 0; I

< match.length; i++) { if (!match[i]) { skip[i] = true; candidates[i] = null; skipped = true; } } } if (!skipped) { return configurations; } List result = new ArrayList(candidates.length); for (int i = 0; i < candidates.length; i++) { if (!skip[i]) { result.add(candidates[i]); } } if (logger.isTraceEnabled()) { int numberFiltered = configurations.size() - result.size(); logger.trace("Filtered " + numberFiltered + " auto configuration class in " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms"); } return new ArrayList(result); } 此方法大致就是首先获取配置的AutoConfigurationImportFilter ,然后对之前获取的所有配置类进行过滤,最后返回过滤之后的配置类;AutoConfigurationImportFilter同样也是通过SpringFactoriesLoader类进行加载类路径下META-INF/spring.factories,只不过当前的key是:org.springframework.boot.autoconfigure.AutoConfigurationImportFilter,可以看一下SpringBoot默认配置的filter: # Auto Configuration Import Filtersorg.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\org.springframework.boot.autoconfigure.condition.OnBeanCondition,\org.springframework.boot.autoconfigure.condition.OnClassCondition,\org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition 可以看到Filter其实就是上文介绍的条件类,这里默认了OnBeanCondition,OnClassCondition以及OnWebApplicationCondition,已这里使用的Mybatis为例看一下MybatisAutoConfiguration的注解: @org.springframework.context.annotation.Configuration@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })@ConditionalOnSingleCandidate(DataSource.class)@EnableConfigurationProperties(MybatisProperties.class)@AutoConfigureAfter(DataSourceAutoConfiguration.class)public class MybatisAutoConfiguration implements InitializingBean {//...以下省略...} 可以看到其中有用到@ConditionalOnClass,表示必须提供SqlSessionFactory和SqlSessionFactoryBean类的情况下才加载此配置类,而整两个是正式Mybatis基础包中提供的;有了基础包还不行,还需要DataSource,而且DataSource必须在MybatisAutoConfiguration实例化之前初始化好,SpringBoot是如何实现,继续看另外一个核心方法selectImports(): @Override public Iterable selectImports() { if (this.autoConfigurationEntries.isEmpty()) { return Collections.emptyList(); } Set allExclusions = this.autoConfigurationEntries.stream() .map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet()); Set processedConfigurations = this.autoConfigurationEntries.stream() .map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream) .collect(Collectors.toCollection(LinkedHashSet::new)); processedConfigurations.removeAll(allExclusions); return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream() .map((importClassName) ->

New Entry (this.entries.get (importClassName), importClassName) .order (Collectors.toList ());} private List sortAutoConfigurations (Set configurations, AutoConfigurationMetadata autoConfigurationMetadata) {return new AutoConfigurationSorter (getMetadataReaderFactory (), autoConfigurationMetadata) .getInPriorityOrder (configurations);}

First, we filter the excluded classes, and then we focus on a method to sort the configuration classes, which is done in the class AutoConfigurationSorter, using getInPriorityOrder ():

Public List getInPriorityOrder (Collection classNames) {AutoConfigurationClasses classes = new AutoConfigurationClasses (this.metadataReaderFactory, this.autoConfigurationMetadata, classNames); List orderedClassNames = new ArrayList (classNames); / / Initially sort alphabetically Collections.sort (orderedClassNames); / / Then sort by order orderedClassNames.sort ((o1, O2)-> {int i1 = classes.get (o1). GetOrder (); int i2 = classes.get (O2). GetOrder (); return Integer.compare (i1, i2);}); / / Then respect @ AutoConfigureBefore @ AutoConfigureAfter orderedClassNames = sortByAnnotation (classes, orderedClassNames); return orderedClassNames }

Order is used to sort first, and then @ AutoConfigureBefore and @ AutoConfigureAfter are used to sort rows. Order is actually sorted through the annotation @ AutoConfigureOrder, and the value is an integer with a structure similar to the following:

@ AutoConfigureOrder (Ordered.HIGHEST_PRECEDENCE + 10)

The literal meaning of @ AutoConfigureBefore and @ AutoConfigureAfter is also easy to understand, specifying before and after other configuration classes, so you can see the following configuration in MybatisAutoConfiguration:

@ AutoConfigureAfter (DataSourceAutoConfiguration.class)

Indicates that the DataSourceAutoConfiguration configuration class will not be loaded until the Mybatis configuration class is loaded, thus resolving the dependency; and the SqlSessionFactory and SqlSession that the Mybatis operation database depends on mentioned above are initialized in MybatisAutoConfiguration SpringBoot itself actually provides a large number of automatic configuration classes of commonly used components. We only need to provide specific conditions to meet. SpringBoot will automatically load initialization and other operations for me, but there must also be requirements for custom configuration classes. Here is a simple example to see how to customize an automatic configuration class.

Custom configuration class

Next, let's take a very simple example to look at the custom process, an example of formatting uppercase messages.

1.pom files introduce dependencies

Com.formatformat-spring-boot-starter0.0.1-SNAPSHOTjarformat-spring-boot-starter http://maven.apache.org 1.8 UTF-8 org.springframework.boot spring-boot-autoconfigure org.springframework.boot spring-boot-dependencies 1.5.2.RELEASE pom import

Spring official Starter is usually named spring-boot-starter- {name} as spring-boot-starter-web,Spring officially recommends that unofficial Starter naming should follow the format of {name}-spring-boot-starter

two。 Service class and attribute configuration class

@ ConfigurationProperties ("format.service") public class FormatServiceProperties {private String type; / /... get/set omitted.} public class FormatService {private String type; public FormatService (String type) {this.type = type;} public String wrap (String word) {if (type.equalsIgnoreCase ("Upper")) {/ / uppercase return word.toUpperCase ();} else if (type.equalsIgnoreCase ("Lower")) {/ / lowercase return word.toLowerCase ();} return word;}}

The property class provides type parameters that can be configured in application.properties. Configurable values include: upper,lower

3. Automatically configure classes and create spring.factories files

@ Configuration@ConditionalOnClass (FormatService.class) @ EnableConfigurationProperties (FormatServiceProperties.class) public class FormatAutoConfigure {@ Autowired private FormatServiceProperties properties; @ Bean @ ConditionalOnMissingBean FormatService formatService () {return new FormatService (properties.getType ());}}

This is the custom automatic configuration class, which is initialized automatically when SpringBoot starts. Finally, create a spring.factories file under resources/META-INF/:

Org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.format.FormatAutoConfigure

4. test

The projects created above can be introduced in other SpringBoot, and in a very simple way:

Com.format format-spring-boot-starter 0.0.1-SNAPSHOT

At the same time, configure the format type in application.properties:

Format.service.type=upper

Start the application, and the browser accesses http://localhost:8888/format?word=hello. The result is: HELLO

This article starts with using SpringBoot to integrate Mybatis, and then raises the questions arising from use, and then understands the automatic configuration mechanism of SpringBoot by analyzing the source code, and finally defines an automatic configuration class to see how to use it; SpringBoot helps developers reduce a lot of work through automatic configuration to achieve the effect of being out of the box; but on the other hand, it may not be so easy to locate if there is a problem that requires debugging.

The above is the editor for you to share how to integrate Mybatis analysis through SpringBoot automatic configuration, if you happen to have similar doubts, you might as well refer to the above analysis to understand. If you want to know more about it, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report