自定义spring boot的自动配置
文章目录
自定义spring boot的自动配置
上篇文章我们讲了spring boot中自动配置的深刻含义和内部结构,这篇文章我们讲一下怎么写出一个自己的自动配置。为了方便和通用起见,这篇文章将会实现一个mysql数据源的自动配置。
添加Maven依赖
我们需要添加mysql和jpa的数据源:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
</dependencies>
创建自定义 Auto-Configuration
我们知道 Auto-Configuration实际上就是一种配置好的@Configuration,所以我们需要创建一个MySQL 的@Configuration, 如下:
@Configuration
public class MySQLAutoconfiguration {
}
下一步就是将这个配置类注册到resources下面的/META-INF/spring.factories作为org.springframework.boot.autoconfigure.EnableAutoConfiguration的一个实现:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.flydean.config.MySQLAutoconfiguration
如果我们希望自定义的@Configuration拥有最高的优先级,我们可以添加@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) 如下所示:
@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
public class MySQLAutoconfiguration {
}
注意, 自动配置的bean只有在该bean没有在应用程序中配置的时候才会自动被配置。如果应用程序中已经配置了该bean,则自动配置的bean会被覆盖。
添加Class Conditions
我们的mysqlConfig只有在DataSource这个类存在的时候才会被自动配置。则可以使用@ConditionalOnClass。 如果某个类不存在的时候生效则可以使用@ConditionalOnMissingClass。
@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(DataSource.class)
public class MySQLAutoconfiguration {
}
添加 bean Conditions
如果我们需要的不是类而是bean的实例,则可以使用@ConditionalOnBean 和 @ConditionalOnMissingBean。
在本例中,我们希望当dataSource的bean存在的时候实例化一个LocalContainerEntityManagerFactoryBean:
@Bean
@ConditionalOnBean(name = "dataSource")
@ConditionalOnMissingBean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan("com.flydean.config.example");
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
if (additionalProperties() != null) {
em.setJpaProperties(additionalProperties());
}
return em;
}
同样的,我们可以定义一个transactionManager, 只有当JpaTransactionManager不存在的时候才创建:
@Bean
@ConditionalOnMissingBean(type = "JpaTransactionManager")
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
Property Conditions
如果我们想在Spring配置文件中的某个属性存在的情况下实例化bean,则可以使用@ConditionalOnProperty。 首先我们需要加载这个Spring的配置文件:
@PropertySource("classpath:mysql.properties")
public class MySQLAutoconfiguration {
//...
}
我们希望属性文件里usemysql=local的时候创建一个DataSource, 则可以这样写:
@Bean
@ConditionalOnProperty(
name = "usemysql",
havingValue = "local")
@ConditionalOnMissingBean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/myDb?createDatabaseIfNotExist=true");
dataSource.setUsername("mysqluser");
dataSource.setPassword("mysqlpass");
return dataSource;
}
Resource Conditions
当我们需要根据resource文件是否存在来实例化bean的时候,可以使用@ConditionalOnResource 。
@ConditionalOnResource(
resources = "classpath:mysql.properties")
@Conditional(HibernateCondition.class)
Properties additionalProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto",
env.getProperty("mysql-hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect",
env.getProperty("mysql-hibernate.dialect"));
hibernateProperties.setProperty("hibernate.show_sql",
env.getProperty("mysql-hibernate.show_sql") != null
? env.getProperty("mysql-hibernate.show_sql") : "false");
return hibernateProperties;
}
我们需要在mysql.properties添加相应的配置:
mysql-hibernate.dialect=org.hibernate.dialect.MySQLDialect
mysql-hibernate.show_sql=true
mysql-hibernate.hbm2ddl.auto=create-drop
Custom Conditions
除了使用@Condition** 之外,我们还可以继承SpringBootCondition来实现自定义的condition。 如下所示:
public class HibernateCondition extends SpringBootCondition {
private static String[] CLASS_NAMES
= { "org.hibernate.ejb.HibernateEntityManager",
"org.hibernate.jpa.HibernateEntityManager" };
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message
= ConditionMessage.forCondition("Hibernate");
return Arrays.stream(CLASS_NAMES)
.filter(className -> ClassUtils.isPresent(className, context.getClassLoader()))
.map(className -> ConditionOutcome
.match(message.found("class")
.items(ConditionMessage.Style.NORMAL, className)))
.findAny()
.orElseGet(() -> ConditionOutcome
.noMatch(message.didNotFind("class", "classes")
.items(ConditionMessage.Style.NORMAL, Arrays.asList(CLASS_NAMES))));
}
}
测试
接下来我们可以测试了:
@RunWith(SpringRunner.class)
@SpringBootTest(
classes = AutoconfigurationApplication.class)
@EnableJpaRepositories(
basePackages = { "com.flydean.repository" })
public class AutoconfigurationTest {
@Autowired
private MyUserRepository userRepository;
@Test
public void whenSaveUser_thenOk() {
MyUser user = new MyUser("user@email.com");
userRepository.save(user);
}
}
这里我们因为没有自定义dataSource所以会自动使用自动配置里面的mysql数据源。
停止自动配置
如果我们不想使用刚刚创建的自动配置该怎么做呢?在@SpringBootApplication中exclude MySQLAutoconfiguration.class即可:
@SpringBootApplication(exclude={MySQLAutoconfiguration.class})
本文的例子可以参考https://github.com/ddean2009/learn-springboot2/tree/master/springboot-custom-autoconfig
更多教程请参考 flydean的博客
自定义spring boot的自动配置的更多相关文章
- 初识Spring Boot框架(二)之DIY一个Spring Boot的自动配置
在上篇博客初识Spring Boot框架中我们初步见识了SpringBoot的方便之处,很多小伙伴可能也会好奇这个Spring Boot是怎么实现自动配置的,那么今天我就带小伙伴我们自己来实现一个简单 ...
- Spring Boot 排除自动配置的 4 种方法,关键时刻很有用!
Spring Boot 提供的自动配置非常强大,某些情况下,自动配置的功能可能不符合我们的需求,需要我们自定义配置,这个时候就需要排除/禁用 Spring Boot 某些类的自动化配置了. 比如:数据 ...
- Spring Boot的自动配置
Spring Boot的自动配置 --摘自https://www.hollischuang.com/archives/1791 随着Ruby.Groovy等动态语言的流行,相比较之下Java的开发显得 ...
- Spring Boot的自动配置原理及启动流程源码分析
概述 Spring Boot 应用目前应该是 Java 中用得最多的框架了吧.其中 Spring Boot 最具特点之一就是自动配置,基于Spring Boot 的自动配置,我们可以很快集成某个模块, ...
- Spring boot 的自动配置
Xml 配置文件 日志 Spring Boot对各种日志框架都做了支持,我们可以通过配置来修改默认的日志的配置: #设置日志级别 logging.level.org.springframework=D ...
- spring boot 系列之六:深入理解spring boot的自动配置
我们知道,spring boot自动配置功能可以根据不同情况来决定spring配置应该用哪个,不应该用哪个,举个例子: Spring的JdbcTemplate是不是在Classpath里面?如果是,并 ...
- 了解Spring Boot的自动配置
摘自:https://www.jianshu.com/p/ddb6e32e3faf Spring Boot的自动配置给开发者带来了很大的便利,当开发人员在pom文件中添加starter依赖后,mave ...
- Spring Boot的自动配置的原理
Spring Boot在进行SpringApplication对象实例化时会加载META-INF/spring.factories文件,将该配置文件中的配置载入到Spring容器. 1.1.1. ...
- Spring Boot的自动配置,到底是怎么做到?
作者:祖大帅 链接:juejin.im/post/5b679fbc5188251aad213110 来源:掘金 1. Spring Boot.Spring MVC 和 Spring 有什么区别? 分开 ...
随机推荐
- U - Inviting Friends HDU - 3244( LIS 最长升序子序列——变形 )
序列变换 Problem Description 我们有一个数列A1,A2-An,你现在要求修改数量最少的元素,使得这个数列严格递增.其中无论是修改前还是修改后,每个元素都必须是整数. 请输出最少需要 ...
- CodeForces - 817B(分类讨论 + 排列组合)
题目链接 思路如下 这一题是:最菜的队伍只有三个人组成,我们只需对排序后的数组的 前三个元素进行分类讨论即可: a[3] != a[2] && a[3] != ar[1] a[3] = ...
- Java 配 Shell 等于美酒加咖啡
化学中我们得知「氢气加氧气在点燃的情况下会生成水」. 生活中我们得知「良辰加美景的情况下会得到千金春宵一刻」. 技术上又何尝不是如此呢?先假设一个场景:BOSS 让你实现一个服务监控的指挥室,能看到每 ...
- Spring的IOC操作
Spring的IOC操作 把对象的创建交给spring ioc操作两个部分 (1)ioc的配置文件方式 (2)ioc基于注解的方式 IOC 的底层原理 1.ioc底层原理使用技术 (1)xml配置文件 ...
- 获取data 数据
export function getData(el, name, val) { const prefix = 'data-' if (val) { return el.setAttribute(pr ...
- C9K Stackwise Virtual(一)
一.SV技术基本说明 思科Catalyst9K平台的Stackwise Virtual技术是将两个物理的交换机虚拟成一个逻辑的实体(从网络控制层面和管理的角度来看),这两个交换机合二为一之后,将共享相 ...
- MyBatis(三):核心配置文件的重要配置-Log
本文是按照狂神说的教学视频学习的笔记,强力推荐,教学深入浅出1便就懂!b站搜索狂神说即可 https://space.bilibili.com/95256449?spm_id_from=333.788 ...
- Vulnhub JIS-CTF-VulnUpload靶机渗透
配置问题解决 参考我的这篇文章https://www.cnblogs.com/A1oe/p/12571032.html更改网卡配置文件进行解决. 信息搜集 找到靶机 nmap -sP 192.168. ...
- javaweb添加学生信息
连接数据库已经进行判断 要求: 1登录账号:要求由6到12位字母.数字.下划线组成,只有字母可以开头:(1分) 2登录密码:要求显示“• ”或“*”表示输入位数,密码要求八位以上字母.数字组成.(1分 ...
- 中阶 d06.1 cookie && session && jsp介绍
##Cookie > 饼干. 其实是一份小数据, 是服务器给客户端,并且存储在客户端上的一份小数据 ### 应用场景 > 自动登录.浏览记录.购物车. ###为什么要有这个Cookie & ...