文章目标
1:简介自动配置类的作用
2:如何实现Spring-data-jpa的自动化配置类
3:简单介绍@conditional核心注解,并且如何运用这些注解
概论
简而言之,Spring Boot自动配置是一种基于类路径上的依赖关系,对Spring应用实现自动配置的方法。 通过重写实现自动配置类中包含的某些bean的需求,这可以使开发更快,更容易。
接下来,我们通过例子,来实现并且了解一下如何实现Spring boot自动化配置类
maven 的依赖
实现Spring-data-jpa的自动化配置类,首先需要加入如下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
选择自己对应的Spring-boot 版本号以及mysql 驱动类的版本
自定义auto-configuration
创建自定义配置类,我们需要创建一个@COnfiguration的注解类,并且进行注册
自定义mysql的数据源配置
@Configuration
public` `class` `MySQLAutoconfiguration {
``//...
}
下一步强制性的就是将自动配置类配置到resources/META-INF/spring.factories:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.john.autoconfiguration.MySQLAutoconfiguration
如果想让自定义的配置类有更高的执行权下,需要在配置类上加上@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)的注解
自动配置类主要是通过在类和bean加入@Conditional的注解,来实现类的自动化配置;只有在应用程序中未定义自动配置的Bean时,自动配置才有效。如果定义了bean,则默认的bean将被覆盖。
conditions 类/以及Spring bean
@CondtionalOnClass注解,表明当某个类出现在扫描的包上,该配置生效
@ConditionalOnMissingClass ;表明当某个类未出现在扫描的包上,该配置就生效
@ConditionalOnBean:当SpringIoc容器内存在指定Bean的条件
@ConditionalOnExpression:基于SpEL表达式作为判断条件
@ConditionalOnJava:基于JVM版本作为判断条件
@ConditionalOnJndi:在JNDI存在时查找指定的位置
@ConditionalOnMissingBean:当SpringIoc容器内不存在指定Bean的条件
@ConditionalOnNotWebApplication:当前项目不是Web项目的条件
@ConditionalOnProperty:指定的属性是否有指定的值
@ConditionalOnResource:类路径是否有指定的值
@ConditionalOnSingleCandidate:当指定Bean在SpringIoc容器内只有一个,或者虽然有多个但是指定首选的Bean
@ConditionalOnWebApplication:当前项目是Web项目的条件
以上注解都是元注解@Conditional演变而来的,根据不用的条件对应创建以上的具体条件注解
condition 类
当我们想自定义一个mysql的配置类,当出现datasource类是就就行如下配置,可以设置如下
@Configuration
@ConditionalOnClass``(DataSource.``class``)
public` `class` `MySQLAutoconfiguration {
``//...
}
condition bean
为了增强配置类的,通过如果有datasource的bean,则创建工厂类;如果没有一个类叫做entityManagerFactory 则创建改bean
@Bean
@ConditionalOnBean(name = "dataSource")
@ConditionalOnMissingBean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan("com.john.autoconfiguration");
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
if (additionalProperties() != null) {
em.setJpaProperties(additionalProperties());
}
return em;
}
如果没有事务管理的bean,则配置事务管理
@Bean
@ConditionalOnMissingBean(type = "JpaTransactionManager")
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
就如上面介绍的 @ConditionalOnProperty 的注解,代表着某个值已经配置化了,就bean生效;首先通过读取特定配置文件,使得JDBC生效;
首先我们引入自定义配置文件中外部变量,
@PropertySource``(``"classpath:mysql.properties"``)
public` `class` `MySQLAutoconfiguration {
``//...
}
在配置文件汇总设置一个mysqlconfig的属性,如果值为local的话,本地的datasource就生效,
@Bean
@ConditionalOnProperty(
name = "mysqlconfig",
havingValue = "local")
@ConditionalOnMissingBean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3307/test?createDatabaseIfNotExist=true");
dataSource.setUsername("mysqluser");
dataSource.setPassword("mysqlpass");
return dataSource;
}
也可以设置一个自定义的datasource;默认的配置如下
@Bean(name = "dataSource")
@ConditionalOnProperty(
name = "usemysql",
havingValue = "custom")
@ConditionalOnMissingBean
public DataSource dataSource2() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl(env.getProperty("mysql.url"));
dataSource.setUsername(env.getProperty("mysql.user") != null
? env.getProperty("mysql.user") : "");
dataSource.setPassword(env.getProperty("mysql.pass") != null
? env.getProperty("mysql.pass") : "");
return dataSource;
}
资源条件
通过@ConditionalOnResource 注解某个具体资源配置i后,某个配置就生效的,让我们定义如下的方法,本地自定义hibernate的自定义condition,重写 *getMatchOutcome* 的方法
参考文章:
网友评论