Article directory
- words written in front
- @Configuration annotation
- @Impot (used on classes) automatically creates imported components for the container
- @Conditional conditional loading annotation
- @ImportResource import Spring configuration file
- Inject the custom configuration of application.properties into the class
- 细嗦@SpringBootApplication
- EnableAutoConfiguration : What have I done?
- **Those 127 configurations will all be loaded but will be allocated on demand according to conditional assembly rules**
- some notes
- To be continued...
words written in front
Because I was frustrated with the project, I came back and brushed springboot for the second time.
Because I am too forgetful, I will take a note and hope that the second brush will allow me to learn some new things
. The time left for me has already exceeded 8. I hope that I will not go to work in the electronics factory in the second half of this year.
@Configuration annotation
This annotation is to mark that this class belongs to springboot management
@Configuration(proxyBeanMethods = true)
If this parameter is true, the same object in the IOC container is used in it.
If it is flase, a new object is created every time it is used.
/**
* 1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
* 2、配置类本身也是组件
* 3、proxyBeanMethods:代理bean的方法
* Full(proxyBeanMethods = true)(保证每个@Bean方法被调用多少次返回的组件都是单实例的)(默认)
* Lite(proxyBeanMethods = false)(每个@Bean方法被调用多少次返回的组件都是新创建的)
*/
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
/**
* Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
* @return
*/
@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖了Pet组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}
@Bean("tom")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}
@Impot (used on classes) automatically creates imported components for the container
Inject with @Import
and then go to the container to see if you can find it
The result is that mypersion
can be found in the IOC container, which
is injected with Bean, and
the long one is injected through Import.
@Conditional conditional loading annotation
There are many annotations
This annotation means that if the IOC container does not have the object mypet, these beans will not be injected
@ImportResource import Spring configuration file
a configuration file
<?xml version="1.0" encoding="UTF-8"?>
<beans ...">
<bean id="haha" class="com.lun.boot.bean.User">
<property name="name" value="zhangsan"></property>
<property name="age" value="18"></property>
</bean>
<bean id="hehe" class="com.lun.boot.bean.Pet">
<property name="name" value="tomcat"></property>
</bean>
</beans>
Use to directly load the bean into the ioc
@ImportResource("classpath:beans.xml")
public class MyConfig {
...
}
test
public static void main(String[] args) {
//1、返回我们IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
boolean haha = run.containsBean("haha");
boolean hehe = run.containsBean("hehe");
System.out.println("haha:"+haha);//true
System.out.println("hehe:"+hehe);//true
}
Inject the custom configuration of application.properties into the class
To inject, we must put what we want to inject into the springboot core configuration file
Use our own class: @Component+@ConfigurationProperties()
We need to inject the two data of mycar into car
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component //把这个类放到容器中
@ConfigurationProperties(prefix="mycar") //读取配置文件中的mycar并把数值给赋给brand和price
public class Car {
private String brand;
private Integer price;
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", price=" + price +
'}';
}
}
When referencing a third-party package: @ConfigurationProperties()+@EnableConfigurationProperties
If we use a third-party library, we can't add @Component to the third-party library,
so we can add @EnableConfigurationProperties to the running class of springboot
let's visit
细嗦@SpringBootApplication
@SpringBootApplication is composed of the following three annotations
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @ComponentScan
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication{
}
@SpringBootConfiguration
This annotation is actually a @Configuration annotation
. This annotation is a sign that this class belongs to springboot management. This annotation has been said before.
Represents that the current class is a configuration class
@ComponentScan
means we want to scan those packages
@EnableAutoConfiguration(重点)
@EnableAutoConfiguration是
- @AutoConfigurationPackage
Synthetic annotation for @Import({AutoConfigurationImportSelector.class})
@AutoConfigurationPackage
Automatic configuration package annotations make default package rules
It is actually an Import annotation (the role is to import a component into the container)
The role of this Registrar is to batch import a series of packages because the source code is too long.
Since it is a designated package to import, which package does it specify?
Of course, the answer is
that this package is spicy
. This also explains a question why it is not started here. The package under the class cannot be scanned
@Import({AutoConfigurationImportSelector.class})
Using the Select mechanism to import in batches
, we enter this class and
find this method
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
Now let's study this thing
autoConfigurationEntry.getConfigurations() batch import components into the container
When we enter this method, we can see that the configuration has undergone a series of operations,
such as taking out and removing the same operations, and finally we get the component we want to import into the container
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
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, exclusions);
configurations.removeAll(exclusions);
configurations = this.getConfigurationClassFilter().filter(configurations);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
This is to get all the configuration classes, we can break the point and take a look
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
Let's debug and this is the configuration we added
Let's enter the getCandidateConfigurations() method to see that it is configured by loading the factory
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
Let's take a look at this factory class
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
Let's go to return and see
that this loads all the configuration methods
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
if (result != null) {
return result;
} else {
try {
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
LinkedMultiValueMap result = new LinkedMultiValueMap();
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 = properties.entrySet().iterator();
while(var6.hasNext()) {
Entry<?, ?> entry = (Entry)var6.next();
String factoryTypeName = ((String)entry.getKey()).trim();
String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
int var10 = var9.length;
for(int var11 = 0; var11 < var10; ++var11) {
String factoryImplementationName = var9[var11];
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
} catch (IOException var13) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
}
}
}
Take a breakpoint
Look at this
. The location of our resource files is here. That is to say, all files in this location in
our current system and this package are scanned by default. This is the 127 configuration class files we loaded above. Springboot has been started to be loaded. 127 configuration classes These configuration classes cover almost all application scenarios of springboot
Let's see how many are
loaded in the startup class. We have loaded 127 plus we must have added more than 129, which means that some of them did not enter the container.
EnableAutoConfiguration : What have I done?
- Load components
- Read the configuration information from the configuration file and set it (referring to reading the configuration file below)
Those 127 configurations will all be loaded but will be allocated on demand according to conditional assembly rules
Let's just go into one and have a look,
we can see this annotation
We mentioned earlier that this is a conditional annotation,
which means that this AOP will only be added to the container under the premise of importing the Advice package.
some notes
Add some annotations for components to the container
- @Bean adds a normal component to the container
- @Component represents a component
- @Controller represents the controller
- @Service represents business logic components
- @Repository represents the database component
- @Impot imports a lot of annotations for the container,
some common annotations - @ComponentScan package scan annotation
To be continued…
The follow-up study notes are all in my spring boot column.
Click to enter the column .