Skip to content

Commit 2636e30

Browse files
committed
ApiBoot Mybatis Enhance 自动化配置
1 parent db82dee commit 2636e30

File tree

5 files changed

+552
-1
lines changed

5 files changed

+552
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
/*
2+
* Copyright [2019] [恒宇少年 - 于起宇]
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package org.minbox.framework.api.boot.autoconfigure.enhance;
19+
20+
import com.gitee.hengboy.mybatis.enhance.EnhanceClassPathMapperScanner;
21+
import com.gitee.hengboy.mybatis.enhance.MapperFactoryBean;
22+
import com.gitee.hengboy.mybatis.enhance.mapper.EnhanceMapper;
23+
import org.apache.ibatis.mapping.DatabaseIdProvider;
24+
import org.apache.ibatis.plugin.Interceptor;
25+
import org.apache.ibatis.session.Configuration;
26+
import org.apache.ibatis.session.ExecutorType;
27+
import org.apache.ibatis.session.SqlSessionFactory;
28+
import org.mybatis.spring.SqlSessionFactoryBean;
29+
import org.mybatis.spring.SqlSessionTemplate;
30+
import org.slf4j.Logger;
31+
import org.slf4j.LoggerFactory;
32+
import org.springframework.beans.BeansException;
33+
import org.springframework.beans.factory.BeanFactory;
34+
import org.springframework.beans.factory.BeanFactoryAware;
35+
import org.springframework.beans.factory.ObjectProvider;
36+
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
37+
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
38+
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
39+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
40+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
41+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
42+
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
43+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
44+
import org.springframework.context.ResourceLoaderAware;
45+
import org.springframework.context.annotation.Bean;
46+
import org.springframework.context.annotation.Import;
47+
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
48+
import org.springframework.core.io.Resource;
49+
import org.springframework.core.io.ResourceLoader;
50+
import org.springframework.core.type.AnnotationMetadata;
51+
import org.springframework.util.Assert;
52+
import org.springframework.util.CollectionUtils;
53+
import org.springframework.util.ObjectUtils;
54+
import org.springframework.util.StringUtils;
55+
56+
import javax.annotation.PostConstruct;
57+
import javax.sql.DataSource;
58+
import java.util.List;
59+
60+
/**
61+
* ApiBoot Mybatis Enhance Auto Configuration
62+
* @author:恒宇少年 - 于起宇
63+
* <p>
64+
* DateTime:2019-04-25 15:16
65+
* Blog:http://blog.yuqiyu.com
66+
* WebSite:http://www.jianshu.com/u/092df3f77bca
67+
* Gitee:https://gitee.com/hengboy
68+
* GitHub:https://github.com/hengboy
69+
*/
70+
@org.springframework.context.annotation.Configuration
71+
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
72+
@ConditionalOnBean(DataSource.class)
73+
@EnableConfigurationProperties(ApiBootMyBatisEnhanceProperties.class)
74+
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
75+
public class ApiBootMyBatisEnhanceAutoConfiguration {
76+
77+
private static final Logger logger = LoggerFactory.getLogger(ApiBootMyBatisEnhanceAutoConfiguration.class);
78+
79+
private final ApiBootMyBatisEnhanceProperties properties;
80+
81+
private final Interceptor[] interceptors;
82+
83+
private final ResourceLoader resourceLoader;
84+
85+
private final DatabaseIdProvider databaseIdProvider;
86+
87+
private final List<ConfigurationCustomizer> configurationCustomizers;
88+
89+
public ApiBootMyBatisEnhanceAutoConfiguration(ApiBootMyBatisEnhanceProperties properties,
90+
ObjectProvider<Interceptor[]> interceptorsProvider,
91+
ResourceLoader resourceLoader,
92+
ObjectProvider<DatabaseIdProvider> databaseIdProvider,
93+
ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) {
94+
this.properties = properties;
95+
this.interceptors = interceptorsProvider.getIfAvailable();
96+
this.resourceLoader = resourceLoader;
97+
this.databaseIdProvider = databaseIdProvider.getIfAvailable();
98+
this.configurationCustomizers = configurationCustomizersProvider.getIfAvailable();
99+
}
100+
101+
@PostConstruct
102+
public void checkConfigFileExists() {
103+
if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) {
104+
Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation());
105+
Assert.state(resource.exists(), "Cannot find config location: " + resource
106+
+ " (please add config file or check your Mybatis configuration)");
107+
}
108+
}
109+
110+
/**
111+
* 实例化SqlSessionFactory对象
112+
*
113+
* @param dataSource 数据源
114+
* @return
115+
* @throws Exception
116+
*/
117+
@Bean
118+
@ConditionalOnMissingBean
119+
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
120+
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
121+
factory.setDataSource(dataSource);
122+
factory.setVfs(SpringBootVFS.class);
123+
if (StringUtils.hasText(this.properties.getConfigLocation())) {
124+
factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
125+
}
126+
Configuration configuration = this.properties.getConfiguration();
127+
if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {
128+
configuration = new Configuration();
129+
}
130+
131+
// 设置自定义列表
132+
if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {
133+
for (ConfigurationCustomizer customizer : this.configurationCustomizers) {
134+
customizer.customize(configuration);
135+
}
136+
}
137+
138+
factory.setConfiguration(configuration);
139+
if (this.properties.getConfigurationProperties() != null) {
140+
factory.setConfigurationProperties(this.properties.getConfigurationProperties());
141+
}
142+
if (!ObjectUtils.isEmpty(this.interceptors)) {
143+
factory.setPlugins(this.interceptors);
144+
}
145+
if (this.databaseIdProvider != null) {
146+
factory.setDatabaseIdProvider(this.databaseIdProvider);
147+
}
148+
if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
149+
factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
150+
}
151+
if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
152+
factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
153+
}
154+
if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
155+
factory.setMapperLocations(this.properties.resolveMapperLocations());
156+
}
157+
158+
return factory.getObject();
159+
}
160+
161+
@Bean
162+
@ConditionalOnMissingBean
163+
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
164+
ExecutorType executorType = this.properties.getExecutorType();
165+
if (executorType != null) {
166+
return new SqlSessionTemplate(sqlSessionFactory, executorType);
167+
} else {
168+
return new SqlSessionTemplate(sqlSessionFactory);
169+
}
170+
}
171+
172+
/**
173+
* This will just scan the same base package as Spring Boot does. If you want
174+
* more power, you can explicitly use
175+
* {@link org.mybatis.spring.annotation.MapperScan} but this will get typed
176+
* mappers working correctly, out-of-the-box, similar to using Spring Data JPA
177+
* repositories.
178+
*/
179+
public static class AutoConfiguredMapperScannerRegistrar
180+
implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware {
181+
182+
private BeanFactory beanFactory;
183+
184+
private ResourceLoader resourceLoader;
185+
186+
@PostConstruct
187+
public void initStatement() {
188+
189+
}
190+
191+
@Override
192+
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
193+
194+
logger.debug("Searching for mappers based with EnhanceMapper.class");
195+
// 重写扫描实现类
196+
// 将扫描到的每一个类
197+
EnhanceClassPathMapperScanner scanner = new EnhanceClassPathMapperScanner(registry);
198+
try {
199+
if (this.resourceLoader != null) {
200+
scanner.setResourceLoader(this.resourceLoader);
201+
}
202+
203+
List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
204+
if (logger.isDebugEnabled()) {
205+
for (String pkg : packages) {
206+
logger.debug("Using auto-configuration base package '{}'", pkg);
207+
}
208+
}
209+
// 通过标记的父接口扫描
210+
scanner.setMarkerInterface(EnhanceMapper.class);
211+
// 通过注解形式扫描
212+
//scanner.setAnnotationClass(Mapper.class);
213+
scanner.registerFilters();
214+
scanner.doScan(StringUtils.toStringArray(packages));
215+
} catch (IllegalStateException ex) {
216+
logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", ex);
217+
}
218+
}
219+
220+
@Override
221+
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
222+
this.beanFactory = beanFactory;
223+
}
224+
225+
@Override
226+
public void setResourceLoader(ResourceLoader resourceLoader) {
227+
this.resourceLoader = resourceLoader;
228+
}
229+
}
230+
231+
/**
232+
* {@link org.mybatis.spring.annotation.MapperScan} ultimately ends up
233+
* creating instances of {@link MapperFactoryBean}. If
234+
* {@link org.mybatis.spring.annotation.MapperScan} is used then this
235+
* auto-configuration is not needed. If it is _not_ used, however, then this
236+
* will bring in a bean registrar and automatically register components based
237+
* on the same component-scanning path as Spring Boot itself.
238+
*/
239+
@org.springframework.context.annotation.Configuration
240+
@Import({AutoConfiguredMapperScannerRegistrar.class})
241+
@ConditionalOnMissingBean(MapperFactoryBean.class)
242+
public static class MapperScannerRegistrarNotFoundConfiguration {
243+
244+
@PostConstruct
245+
public void afterPropertiesSet() {
246+
logger.debug("No {} found.", MapperFactoryBean.class.getName());
247+
}
248+
}
249+
}

0 commit comments

Comments
 (0)