Lag en egendefinert autokonfigurasjon med Spring Boot

1. Oversikt

Enkelt sagt, Spring Boot autokonfigurasjon representerer en måte å automatisk konfigurere en Spring-applikasjon basert på avhengighetene som er tilstede på klassestien.

Dette kan gjøre utviklingen raskere og enklere ved å eliminere behovet for å definere visse bønner som er inkludert i autokonfigurasjonsklassene.

I det neste avsnittet skal vi ta en titt på lage vår egendefinerte Auto Boot-konfigurasjon.

2. Maven-avhengigheter

La oss starte med avhengighetene vi trenger:

 org.springframework.boot spring-boot-starter-data-jpa 2.2.2.RELEASE mysql mysql-connector-java 8.0.19 

De siste versjonene av spring-boot-starter-data-jpa og mysql-connector-java kan lastes ned fra Maven Central.

3. Opprette en tilpasset autokonfigurasjon

For å opprette en tilpasset automatisk konfigurasjon, må vi opprette en klasse som er merket som @Konfigurasjon og registrer det.

La oss lage en tilpasset konfigurasjon for en MySQL datakilde:

@Configuration public class MySQLAutoconfiguration {// ...}

Det neste obligatoriske trinnet er å registrere klassen som en automatisk konfigurasjonskandidat, ved å legge til navnet på klassen under nøkkelen org.springframework.boot.autoconfigure.EnableAutoConfiguration i standardfilen ressurser / META-INF / vårfabrikker:

org.springframework.boot.autoconfigure.EnableAutoConfiguration = \ com.baeldung.autoconfiguration.MySQLAutoconfiguration

Hvis vi vil at vår autokonfigurasjonsklasse skal ha prioritet foran andre autokonfigurasjonskandidater, kan vi legge til @AutoConfigureOrder (bestilt. HØYESTE_PRECEDENS) kommentar.

Autokonfigurasjon er designet med klasser og bønner merket med @Betinget merknader slik at den automatiske konfigurasjonen eller spesifikke deler av den kan erstattes.

Vær oppmerksom på at den automatiske konfigurasjonen bare gjelder hvis de automatisk konfigurerte bønnene ikke er definert i applikasjonen. Hvis du definerer bønnen din, blir den standard overstyrt.

3.1. Klasseforhold

Klasseforholdene tillater oss å spesifiser at en konfigurasjonsbønne vil være inkludert hvis en spesifisert klasse er til stede bruker @ConditionalOnClass kommentar, eller hvis en klasse er fraværende bruker @ConditionalOnMissingClass kommentar.

La oss spesifisere at vår MySQLConfiguration vil bare bli lastet hvis klassen Datakilde er til stede, i så fall kan vi anta at applikasjonen vil bruke en database:

@Configuration @ConditionalOnClass (DataSource.class) offentlig klasse MySQLAutoconfiguration {// ...}

3.2. Bønneforhold

Hvis vi vil inkluderer bare en bønne hvis en spesifisert bønne er tilstede eller ikke, kan vi bruke @ConditionalOnBean og @ConditionalOnMissingBean kommentarer.

For å eksemplifisere dette, la oss legge til en entityManagerFactory bønne til vår konfigurasjonsklasse, og spesifiser at vi bare vil at denne bønnen skal opprettes hvis en bønne ringte datakilde er til stede og hvis en bønne ringte entityManagerFactory er ikke allerede definert:

@Bean @ConditionalOnBean (name = "dataSource") @ConditionalOnMissingBean public LocalContainerEntityManagerFactoryBean entityManagerFactory () {LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean (); em.setDataSource (dataSource ()); em.setPackagesToScan ("com.baeldung.autoconfiguration.example"); em.setJpaVendorAdapter (ny HibernateJpaVendorAdapter ()); hvis (additionalProperties ()! = null) {em.setJpaProperties (additionalProperties ()); } returner dem; }

La oss også konfigurere en transactionManager bønne som bare blir lastet hvis en bønne av typen JpaTransactionManager er ikke allerede definert:

@Bean @ConditionalOnMissingBean (type = "JpaTransactionManager") JpaTransactionManager transactionManager (EntityManagerFactory entityManagerFactory) {JpaTransactionManager transactionManager = ny JpaTransactionManager (); transactionManager.setEntityManagerFactory (entityManagerFactory); returtransaksjonManager; }

3.3. Eiendomsforhold

De @ConditionalOnProperty merknader er vant til spesifiser om en konfigurasjon skal lastes inn basert på tilstedeværelsen og verdien til en Spring Environment-egenskap.

Først, la oss legge til en eiendomskildefil for konfigurasjonen vår som vil bestemme hvor egenskapene skal leses fra:

@PropertySource ("classpath: mysql.properties") offentlig klasse MySQLAutoconfiguration {// ...}

Vi kan konfigurere hoveddelen Datakilde bønne som skal brukes til å opprette forbindelser til databasen på en slik måte at den bare lastes inn hvis en eiendom ringte usemysql er tilstede.

Vi kan bruke attributtet å ha verdi for å spesifisere bestemte verdier for usemysql eiendom som må matches.

La oss definere datakilde bønne med standardverdier som kobles til en lokal database kalt myDb hvis usemysql eiendommen er satt til lokal:

@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"); returner datakilde; }

Hvis den usemysql eiendommen er satt til tilpasset, de datakilde bean vil bli konfigurert ved hjelp av egendefinerte egenskaper for databasens URL, bruker og passord:

@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"): ""); returner datakilde; }

De mysql.properties filen vil inneholde usemysql eiendom:

usemysql = lokal

Hvis et program som bruker MySQLAutokonfigurasjon ønsker å overstyre standardegenskapene, alt det trenger å gjøre er å legge til forskjellige verdier for mysql.url, mysql.user og mysql.pass eiendommer og usemysql = tilpasset linje i mysql.properties fil.

3.4. Ressursforhold

Legge til @ConditionalOnResource merknad betyr at konfigurasjonen lastes bare når en spesifisert ressurs er til stede.

La oss definere en metode som heter tilleggsegenskaper () som vil returnere a Eiendommer objekt som inneholder dvalespesifikke egenskaper som skal brukes av entityManagerFactory bønne, bare hvis ressursfilen mysql.properties er tilstede:

@ConditionalOnResource (resources = "classpath: mysql.properties") @Conditional (HibernateCondition.class) Egenskaper 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"); returnere dvaleegenskaper; }

Vi kan legge til de spesifikke egenskapene for dvalemodus i mysql.properties fil:

mysql-hibernate.dialect = org.hibernate.dialect.MySQLDialect mysql-hibernate.show_sql = true mysql-hibernate.hbm2ddl.auto = create-drop

3.5. Egendefinerte forhold

Hvis vi ikke vil bruke noen av betingelsene som er tilgjengelige i Spring Boot, kan vi også definere egendefinerte forhold ved å utvide SpringBootCondition klasse og overordnet getMatchOutcome () metode.

La oss lage en tilstand som heter Dvalemodus for vår tilleggsegenskaper () metode som vil verifisere om en HibernateEntityManager klasse er til stede på klassestien:

statisk klasse HibernateCondition utvider SpringBootCondition {privat statisk streng [] 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)))); }}

Så kan vi legge til tilstanden til tilleggsegenskaper () metode:

@Conditional (HibernateCondition.class) Egenskaper additionalProperties () {// ...}

3.6. Søknadsbetingelser

Vi kan også spesifiser at konfigurasjonen bare kan lastes innenfor / utenfor en nettkontekst, ved å legge til @ConditionalOnWebApplication eller @ConditionalOnNotWebApplication kommentar.

4. Testing av autokonfigurasjonen

La oss lage et veldig enkelt eksempel for å teste vår autokonfigurasjon. Vi vil opprette en enhetsklasse kalt Min bruker, og en MyUserRepository grensesnitt ved hjelp av vårdata:

@Entity offentlig klasse MyUser {@Id privat streng-e-post; // standard konstruktør, getters, setters}
offentlig grensesnitt MyUserRepository utvider JpaRepository {}

For å aktivere autokonfigurasjon kan vi bruke en av @SpringBootApplication eller @EnableAutoConfiguration kommentarer:

@SpringBootApplication public class AutoconfigurationApplication {public static void main (String [] args) {SpringApplication.run (AutoconfigurationApplication.class, args); }}

La oss deretter skrive en JUnit test som sparer en Min bruker enhet:

@RunWith (SpringJUnit4ClassRunner.class) @SpringBootTest (klasser = AutoconfigurationApplication.class) @EnableJpaRepositories (basePackages = {"com.baeldung.autoconfiguration.example"}) offentlig klasse AutoconfigurationTest {@Autowired private MyRepository; @Test offentlig ugyldig nårSaveUser_thenOk () {MyUser user = new MyUser ("[email protected]"); userRepository.save (bruker); }}

Siden vi ikke har definert våre Datakilde konfigurasjon, vil applikasjonen bruke den automatiske konfigurasjonen vi har opprettet for å koble til en MySQL database kalt myDb.

Tilkoblingsstrengen inneholder createDatabaseIfNotExist = true eiendom, slik at databasen ikke trenger å eksistere. Imidlertid brukeren mysqluser eller den som er spesifisert gjennom mysql.user eiendom hvis den er tilstede, må opprettes.

Vi kan sjekke applikasjonsloggen for å se at MySQL datakilde brukes:

web - 2017-04-12 00: 01: 33,956 [main] INFO o.s.j.d.DriverManagerDataSource - Lastet JDBC-driver: com.mysql.cj.jdbc.Driver

5. Deaktivering av autokonfigurasjonsklasser

Hvis vi ville ekskluder at autokonfigurasjonen blir lastet, kan vi legge til @EnableAutoConfiguration kommentar med utelukke eller ekskluder Navn attributt til en konfigurasjonsklasse:

@Configuration @EnableAutoConfiguration (ekskluder = {MySQLAutoconfiguration.class}) offentlig klasse AutoconfigurationApplication {// ...}

Et annet alternativ for å deaktivere spesifikke autokonfigurasjoner er å stille inn spring.autoconfigure.exclude eiendom:

spring.autoconfigure.exclude = com.baeldung.autoconfiguration.MySQLAutoconfiguration

6. Konklusjoner

I denne veiledningen har vi vist hvordan du oppretter en tilpasset Spring Boot automatisk konfigurasjon. Den fulle kildekoden til eksemplet finner du på GitHub.

JUnit-testen kan kjøres ved hjelp av autokonfigurasjon profil: mvn ren installasjon -autokonfigurasjon.


$config[zx-auto] not found$config[zx-overlay] not found