1. Why can I achieve automatic configuration using @SpringBootApplication annotation?
Answer: @SpringBootApplication, there are actually 3 internal annotations. @EnableAutoConfiguration, @ComponentScan, @Configuration. This article mainly explains @EnableXX annotation
2. Why is @EnableAutoConfiguration used? When @ConfigurationProperties is used, the configuration items in .yml or .properties can be automatically imported?
Answer: Inside @EnableAutoConfiguration, the @Import annotation is used. Import AutoConfigurationImportSelector helps springBoot load the qualified configuration into the IOC container. But the internal use of SpringFactoriesLoader is used to complete it. Similar to Java SPI, that is, loading configuration from /META-INF/spring.factories
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import({AutoConfigurationImportSelector.class})public @interface EnableAutoConfigurationYou can see that in @Import, an AutoConfigurationImportSelector class is actually imported. The most important thing is that this class implements the interface ImportSelector
public interface ImportSelector { /** * Select and return the names of which class(es) should be imported based on * the {@link AnnotationMetadata} of the importing @{@link Configuration} class. */ String[] selectImports(AnnotationMetadata importingClassMetadata);}This is the description of ImportSelector, which roughly means that the bean returned by this method will be automatically injected and managed by Spring.
Next, let’s look at the implementation of selectImports in AutoConfigurationImportSelector
public String[] selectImports(AnnotationMetadata annotationMetadata) { if(!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); AnnotationAttributes attributes = this.getAttributes(annotationMetadata); List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes); configurations = this.removeDuplicates(configurations); Set<String> exclusions = this.getExclusions(annotationMetadata, attributes); this.checkExcludedClasses(configurations, exclus); configurations.removeAll(exclusions); configurations = this.filter(configurations, autoConfigurationMetadata); this.fireAutoConfigurationImportEvents(configurations, excclusions); return StringUtils.toStringArray(configurations); } }The code is written very clearly. I won't explain it.
In @Import, you can see that a link points to ImportBeanDefinitionRegistrar. This is also an interface, and its function is the same as ImportSelector.
public interface ImportBeanDefinitionRegistrar { public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);}In the registerBeanDefinitions method, you can use BeanDefinitionRegistry to inject the bean we want to inject.
Code example:
Write your own @Enable using @Import
1. Create 2 test beans
public class Role {}public class User {}2. Customize Enable annotations
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Import(MyEnableAutoConfig.class)public @interface EnableBean {}3. Implement your own EnableAutoConfiguration class
public class MyEnableAutoConfig implements ImportSelector{ @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{"com.xhn2.Role","com.xhn2.User"}; }}4. Write a startup class
@EnableBean@ComponentScan("com.xhn2")public class Main { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(Main.class, args); System.out.println(context.getBean(User.class)); System.out.println(context.getBean(Role.class)); }}5. Operation results
com.xhn2.User@496bc455
com.xhn2.Role@59402b8f
The console prints successfully.
Code example 2, automatic assembly of the third party jar package
New maven project
1. pom.xml
<modelVersion>4.0.0</modelVersion> <groupId>org.csp</groupId> <artifactId>hello</artifactId> <version>1.0.0</version> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.17.RELEASE</version> </dependency> </dependencies>
2. Write Configuration
@Configurationpublic class MyTest { @Bean public Runnable runnable() { return ()->{}; }}Create a new META-INF/spring.factories file under resources and add the following configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.edu.MyTest
3. Install the project to the local maven repository: mvn install
4. The main project introduces the jar that has just been installed to the local area.
<dependency> <groupId>org.csp</groupId> <artifactId>hello</artifactId> <version>1.0.0</version> </dependency>
5. Get the Runnable configured just now
@SpringBootApplicationpublic class Main { public static void main(String[] args) { SpringApplication application = new SpringApplication(Main.class); ConfigurableApplicationContext context = application.run(args); System.out.println(context.getBean(Runnable.class)); }}6. Console printing
com.edu.MyTest$$Lambda$153/284686302@2c07545f
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.