更新時間:2022-05-16 10:10:28 來源:動力節點 瀏覽2470次
簡單地說,Spring Boot 自動配置代表了一種基于類路徑中存在的依賴項自動配置 Spring 應用程序的方法。
通過消除定義自動配置類中包含的某些 bean 的需要,這可以使開發更快、更容易。
讓我們從我們需要的Maven依賴項開始:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
最新版本的spring-boot-starter-data-jpa和mysql-connector-java可以從 Maven Central 下載。
要創建自定義自動配置,我們需要創建一個注釋為@Configuration的類并注冊它。
讓我們為MySQL數據源創建一個自定義配置:
@Configuration
public class MySQLAutoconfiguration {
//...
}
下一個強制性步驟是將類注冊為自動配置候選者,方法是在標準文件resources/META-INF/spring.factories中的鍵org.springframework.boot.autoconfigure.EnableAutoConfiguration下添加類的名稱:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.baeldung.autoconfiguration.MySQLAutoconfiguration
如果我們希望我們的自動配置類優先于其他自動配置候選者,我們可以添加@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)注釋。
自動配置是使用標有@Conditional注釋的類和 bean 設計的,以便可以替換自動配置或其特定部分。
請注意,僅當應用程序中未定義自動配置的 bean 時,自動配置才有效。如果你定義你的bean,那么默認的將被覆蓋。
(1)班級條件
類條件允許我們使用@ConditionalOnClass注解指定如果指定的類存在,或者使用@ConditionalOnMissingClass注解不存在類,則將包含配置 bean。
讓我們指定只有當DataSource類存在時才會加載我們的MySQLConfiguration,在這種情況下,我們可以假設應用程序將使用數據庫:
@Configuration
@ConditionalOnClass(DataSource.class)
public class MySQLAutoconfiguration {
//...
}
(2)bean條件
如果我們只想在指定的 bean 存在或不存在時才包含 bean,我們可以使用@ConditionalOnBean和@ConditionalOnMissingBean注釋。
為了舉例說明這一點,讓我們在配置類中添加一個entityManagerFactory bean,并指定我們只希望在存在名為dataSource的 bean 并且尚未定義名為entityManagerFactory的 bean 時創建此 bean:
@Bean
@ConditionalOnBean(name = "dataSource")
@ConditionalOnMissingBean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan("com.baeldung.autoconfiguration.example");
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
if (additionalProperties() != null) {
em.setJpaProperties(additionalProperties());
}
return em;
}
讓我們還配置一個transactionManager bean,僅當JpaTransactionManager類型的 bean尚未定義時才會加載:
@Bean
@ConditionalOnMissingBean(type = "JpaTransactionManager")
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
(3)條件
@ConditionalOnProperty注釋用于指定是否將基于 Spring Environment 屬性的存在和值來加載配置。
首先,讓我們為我們的配置添加一個屬性源文件,該文件將確定從何處讀取屬性:
@PropertySource("classpath:mysql.properties")
public class MySQLAutoconfiguration {
//...
}
我們可以配置將用于創建與數據庫的連接的主DataSource bean,只有在存在名為usemysql的屬性時才會加載它。
我們可以使用屬性havingValue來指定必須匹配的usemysql屬性的某些值。
如果usemysql屬性設置為local ,讓我們使用默認值定義dataSource bean,該值連接到名為myDb的本地數據庫:
@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;
}
如果usemysql屬性設置為custom, dataSource bean將使用數據庫 URL、用戶和密碼的自定義屬性值進行配置:
@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;
}
mysql.properties文件將包含usemysql屬性:
usemysql=local
如果使用MySQLAutoconfiguration的應用程序希望覆蓋默認屬性,它所需要做的就是為mysql.url、mysql.user和mysql.pass屬性以及mysql.properties文件中的usemysql=custom行添加不同的值。
(4)資源條件
添加@ConditionalOnResource注解意味著只有在指定資源存在時才會加載配置。
讓我們定義一個名為additionalProperties()的方法,該方法將返回一個Properties對象,其中包含要由entityManagerFactory bean 使用的 Hibernate 特定屬性,僅當資源文件mysql.properties存在時:
@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;
}
我們可以將 Hibernate 特定的屬性添加到mysql.properties文件中:
mysql-hibernate.dialect=org.hibernate.dialect.MySQLDialect
mysql-hibernate.show_sql=true
mysql-hibernate.hbm2ddl.auto=create-drop
(5)自定義條件
如果我們不想使用 Spring Boot 中可用的任何條件,我們還可以通過擴展SpringBootCondition類并覆蓋getMatchOutcome()方法來定義自定義條件。
讓我們為additionalProperties()方法創建一個名為HibernateCondition的條件,該方法將驗證HibernateEntityManager類是否存在于類路徑中:
static 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(Style.NORMAL, className)))
.findAny()
.orElseGet(() -> ConditionOutcome
.noMatch(message.didNotFind("class", "classes")
.items(Style.NORMAL, Arrays.asList(CLASS_NAMES))));
}
}
然后我們可以將條件添加到additionalProperties()方法中:
@Conditional(HibernateCondition.class)
Properties additionalProperties() {
//...
}
(6)申請條件
我們還可以通過添加@ConditionalOnWebApplication或@ConditionalOnNotWebApplication注釋來指定配置只能在 Web 上下文內部/外部加載。
讓我們創建一個非常簡單的示例來測試我們的自動配置。我們將使用 Spring Data創建一個名為MyUser的實體類和一個MyUserRepository接口:
@Entity
public class MyUser {
@Id
private String email;
// standard constructor, getters, setters
}
public interface MyUserRepository
extends JpaRepository<MyUser, String> { }
要啟用自動配置,我們可以使用@SpringBootApplication或@EnableAutoConfiguration注釋之一:
@SpringBootApplication
public class AutoconfigurationApplication {
public static void main(String[] args) {
SpringApplication.run(AutoconfigurationApplication.class, args);
}
}
接下來,讓我們編寫一個保存MyUser實體的JUnit測試:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(
classes = AutoconfigurationApplication.class)
@EnableJpaRepositories(
basePackages = { "com.baeldung.autoconfiguration.example" })
public class AutoconfigurationTest {
@Autowired
private MyUserRepository userRepository;
@Test
public void whenSaveUser_thenOk() {
MyUser user = new MyUser("[email protected]");
userRepository.save(user);
}
}
由于我們尚未定義DataSource配置,因此應用程序將使用我們創建的自動配置連接到名為myDb的MySQL數據庫。
連接字符串包含createDatabaseIfNotExist=true屬性,因此數據庫不需要存在。但是,需要創建用戶mysqluser或通過mysql.user屬性指定的用戶(如果存在)。
我們可以檢查應用程序日志來查看MySQL數據源是否正在被使用:
web - 2017-04-12 00:01:33,956 [main] INFO o.s.j.d.DriverManagerDataSource - Loaded JDBC driver: com.mysql.cj.jdbc.Driver
如果我們想從加載中排除自動配置,我們可以將帶有exclude或excludeName屬性的@EnableAutoConfiguration注解添加到配置類中:
@Configuration
@EnableAutoConfiguration(
exclude={MySQLAutoconfiguration.class})
public class AutoconfigurationApplication {
//...
}
禁用特定自動配置的另一個選項是設置spring.autoconfigure.exclude屬性:
spring.autoconfigure.exclude=com.baeldung.autoconfiguration.MySQLAutoconfiguration
以上就是關于“使用SpringBoot自定義配置文件”的介紹,如果大家想了解更多相關知識,可以關注一下動力節點的SpringBoot教程,教程內容從淺到深,通俗易懂,適合小白學習,希望對大家能夠有所幫助。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習