Opret en brugerdefineret automatisk konfiguration med Spring Boot

1. Oversigt

Kort sagt, Spring Boot-autokonfigurationen repræsenterer en måde til automatisk at konfigurere en Spring-applikation baseret på de afhængigheder, der findes på klassestien.

Dette kan gøre udviklingen hurtigere og lettere ved at eliminere behovet for at definere bestemte bønner, der er inkluderet i de automatiske konfigurationsklasser.

I det følgende afsnit skal vi se på opretter vores brugerdefinerede Auto Boot-konfiguration.

2. Maven-afhængigheder

Lad os starte med de afhængigheder, vi har brug for:

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

De nyeste versioner af spring-boot-starter-data-jpa og mysql-connector-java kan downloades fra Maven Central.

3. Oprettelse af en brugerdefineret automatisk konfiguration

For at oprette en brugerdefineret automatisk konfiguration skal vi oprette en klasse, der er kommenteret som @Konfiguration og registrer det.

Lad os oprette en brugerdefineret konfiguration til en MySQL datakilde:

@Configuration offentlig klasse MySQLAutoconfiguration {// ...}

Det næste obligatoriske trin er at registrere klassen som en automatisk konfigurationskandidat ved at tilføje klassens navn under nøglen org.springframework.boot.autoconfigure.EnableAutoConfiguration i standardfilen ressourcer / META-INF / spring.fabrikker:

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

Hvis vi ønsker, at vores autokonfigurationsklasse skal have prioritet over andre kandidater til automatisk konfiguration, kan vi tilføje @AutoConfigureOrder (bestilt. HIGHEST_PRECEDENCE) kommentar.

Automatisk konfiguration er designet ved hjælp af klasser og bønner markeret med @Betinget bemærkninger, så den automatiske konfiguration eller specifikke dele af den kan udskiftes.

Bemærk, at den automatiske konfiguration kun er i kraft, hvis de automatisk konfigurerede bønner ikke er defineret i applikationen. Hvis du definerer din bønne, tilsidesættes standardbønnen.

3.1. Klasseforhold

Klasseforhold tillader os at angiv, at en konfigurationsbønne vil blive inkluderet, hvis en specificeret klasse er til stede bruger @ConditionalOnClass kommentar, eller hvis en klasse er fraværende bruger @ConditionalOnMissingClass kommentar.

Lad os specificere, at vores MySQLConfiguration vil kun blive indlæst, hvis klassen Datakilde er til stede, i hvilket tilfælde vi kan antage, at applikationen bruger en database:

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

3.2. Bønneforhold

Hvis vi vil Inkluder kun en bønne, hvis en bestemt bønne er til stede eller ej, kan vi bruge @ConditionalOnBean og @ConditionalOnMissingBean kommentarer.

Lad os tilføje en for at eksemplificere dette entityManagerFactory bønne til vores konfigurationsklasse, og angiv, at vi kun ønsker, at denne bønne skal oprettes, hvis en bønne ringede datakilde er til stede, og hvis en bønne kaldes entityManagerFactory er ikke allerede defineret:

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

Lad os også konfigurere en transactionManager bønne, der kun indlæses, hvis en bønne af typen JpaTransactionManager er ikke allerede defineret:

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

3.3. Ejendomsbetingelser

Det @ConditionalOnProperty kommentar bruges til angiv, om en konfiguration vil blive indlæst baseret på tilstedeværelsen og værdien af ​​en Spring Environment-egenskab.

Lad os først tilføje en egenskabskildefil til vores konfiguration, der bestemmer, hvor egenskaberne læses fra:

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

Vi kan konfigurere det vigtigste Datakilde bønne, der vil blive brugt til at oprette forbindelser til databasen på en sådan måde, at den kun indlæses, hvis en egenskab kaldes usemysql er til stede.

Vi kan bruge attributten have værdi for at specificere bestemte værdier for usemysql ejendom, der skal matches.

Lad os definere datakilde bønne med standardværdier, der opretter forbindelse til en lokal database, der kaldes myDb hvis den usemysql ejendom er indstillet 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"); returnere datakilde; }

Hvis den usemysql ejendom er indstillet til brugerdefinerede, det datakilde bønne konfigureres ved hjælp af brugerdefinerede egenskabsværdier til database URL, bruger og adgangskode:

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

Det mysql.properties filen indeholder usemysql ejendom:

usemysql = lokal

Hvis et program, der bruger MySQLAutokonfiguration ønsker at tilsidesætte standardegenskaberne, alt hvad den skal gøre er at tilføje forskellige værdier til mysql.url, mysql.user og mysql.pass egenskaber og usemysql = brugerdefineret linje i mysql.properties fil.

3.4. Ressourceforhold

Tilføjelse af @ConditionalOnResource kommentar betyder, at konfiguration indlæses kun, når en bestemt ressource er til stede.

Lad os definere en metode kaldet additionalProperties () der vil returnere en Ejendomme objekt, der indeholder dvale-specifikke egenskaber, der skal bruges af entityManagerFactory bønne, kun hvis ressourcefilen mysql.properties er til stede:

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

Vi kan tilføje de dvale-specifikke egenskaber til mysql.properties fil:

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

3.5. Brugerdefinerede betingelser

Hvis vi ikke ønsker at bruge nogen af ​​de betingelser, der er tilgængelige i Spring Boot, kan vi også definere brugerdefinerede betingelser ved at udvide SpringBootCondition klasse og overordnet getMatchOutcome () metode.

Lad os oprette en betingelse kaldet Dvaletilstand for vores additionalProperties () metode, der vil kontrollere, om en HibernateEntityManager klasse er til stede på klassestien:

statisk klasse HibernateCondition udvider 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 ("Dvaletilstand"); returnere 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 tilføje betingelsen til additionalProperties () metode:

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

3.6. Ansøgningsbetingelser

Det kan vi også angiv, at konfigurationen kun kan indlæses inden for / uden for en webkontekstved at tilføje @ConditionalOnWebApplication eller @ConditionalOnNotWebApplication kommentar.

4. Test af automatisk konfiguration

Lad os oprette et meget simpelt eksempel for at teste vores autokonfiguration. Vi opretter en enhedsklasse kaldet MyUserog en MyUserRepository interface ved hjælp af Spring Data:

@Entity offentlig klasse MyUser {@Id privat streng-e-mail; // standard konstruktør, getters, setters}
offentlig grænseflade MyUserRepository udvider JpaRepository {}

For at aktivere automatisk konfiguration kan vi bruge en af @SpringBootApplication eller @EnableAutoConfiguration kommentarer:

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

Lad os derefter skrive en JUnit test der sparer en MyUser enhed:

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

Da vi ikke har defineret vores Datakilde konfiguration, vil applikationen bruge den automatiske konfiguration, vi har oprettet til at oprette forbindelse til en MySQL database kaldet myDb.

Forbindelsesstrengen indeholder createDatabaseIfNotExist = true egenskab, så databasen behøver ikke at eksistere. Dog brugeren mysqluser eller den, der er angivet gennem mysql.user ejendom, hvis den er til stede, skal oprettes.

Vi kan kontrollere applikationsloggen for at se, at MySQL datakilde bruges:

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

5. Deaktivering af autokonfigurationsklasser

Hvis vi ville ekskluder automatisk konfiguration fra at blive indlæst, kunne vi tilføje @EnableAutoConfiguration kommentar med udelukke eller excludeName attribut til en konfigurationsklasse:

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

En anden mulighed for at deaktivere specifikke automatiske konfigurationer er ved at indstille spring.autoconfigure.exclude ejendom:

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

6. Konklusioner

I denne vejledning har vi vist, hvordan man opretter en tilpasset Spring Boot-automatisk konfiguration. Den fulde kildekode for eksemplet kan findes på GitHub.

JUnit-testen kan køres ved hjælp af autokonfiguration profil: mvn ren installation -autokonfiguration.


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