自动化装配步骤:
1.新建一个组件项目
2.在resources下
新建META-INF/spring.factories
新建META-INF/spring-autoconfigure-metadata.properties (可选)(可由 条件注解替代)
3.写一个JavaConfig配置类,并在类中写入需要注入的BeanX
4.maven-intall 生成 jar包
5.在新项目中引入该jar包的依赖
6.直接注入BeanX即可。(IOC容器自动加载)
源码解析
AutoConfigurationImportSelector源码解析
- AutoConfigurationImportSelector是Spring实现自动装配Bean的核心类,selectImports是其核心方法。方法作用:加载spring-autoconfigure-metadata.properties的条件,加载sprng.factories的配置类。然后加入过滤条件,交给IOC去创建对象。
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
//1.获取classpath下META-INF所有的spring-autoconfidure-metadata.propeerties所有过滤条件
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
//2.获取classpath下META-INF下所有的spring.factories
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
//返回所有需要加载的类的全路径,交给IOC去创建对象
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
2.通过FactoriesClassLoad工具加载META-INF下所有的spring.factories,通过key(注解全路径作为key),获取所有的value,value值为自动注入Bean的全路径,然后加入过滤条件,返回。
/**
* Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}
* of the importing {@link Configuration @Configuration} class.
* @param autoConfigurationMetadata the auto-configuration metadata
* @param annotationMetadata the annotation metadata of the configuration class
* @return the auto-configurations that should be imported
*/
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
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;
}
自动化装配实现
根据条件注入Bean
根据条件注入Bean实现方式:
- 基于spring-autoconfigure-metadata.properties配置文件实现
新建项目 gupao-core ,作为一个组件进行编写。无需注入完整的依赖。
包结构:
pom.xml
只需要可以使用@Configuration注解、@Bean注解即可,所以只注入了context包,无需注入完整的spring包
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>gupao-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
</dependencies>
</project>
java代码
@Configuration
@Configuration
public class GuPaoConfig {
@Bean
public Student student(){
return new Student();
}
}
@Configuration
public class GuPaoOtherConfig {
@Bean
public People people(){
return new People();
}
}
在resources下新建/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.gupao.core.GuPaoConfig,\
com.gupao.core.GuPaoOtherConfig
在resources下新建/META-INF/spring-autoconfigure-metadata.properties
com.gupao.core.GuPaoConfig.ConditionalOnClass=com.differ.demo5.Test
然后使用maven工具 install生成jar包
新建项目 gupao ,引入组件gupao-core,实现自动装配
在gupao的pom.xml中引入组件的依赖。
<dependency>
<groupId>com</groupId>
<artifactId>gupao-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
@SpringBootApplication
public class App {
public static void main(String[] args) {
ConfigurableApplicationContext ca = SpringApplication.run(App.class, args);
People bean = ca.getBean(People.class);
Student dog = ca.getBean(Student.class);
System.out.println(bean.say());
System.out.println(dog.say());
}
}
Console控制台打印
2019-09-03 19:22:05.449 INFO 5640 --- [ main] com.differ.demo5.App : No active profile set, falling back to default profiles: default
2019-09-03 19:22:09.090 INFO 5640 --- [ main] com.differ.demo5.App : Started App in 11.176 seconds (JVM running for 21.484)
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.gupao.core.Student' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:346)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:337)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1123)
at com.differ.demo5.App.main(App.java:17)
报错原因: 由于组件加入了条件。 所以必须在主项目中加入相应的条件才不会报错。
在guapo项目中,新建一个类即可。
com.differ.demo5.Test
- 基于条件注解,实现自动装配
基于注解实现—> 条件注解
@ConditionOnClass
@Condi…
…
新建项目 gupao-core ,作为一个组件进行编写。无需注入完整的依赖。
包结构:
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com-gupao</groupId>
<artifactId>gupao-core2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
java代码
@Configuration
@ConditionalOnClass(name={"com.differ.demo5.TestA"})
public class SpringConfig {
@Bean
public People people(){
return new People();
}
}
在resources下新建/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.gupao.core.GuPaoConfig
然后使用maven工具 install生成jar包
新建项目 gupao ,引入组件gupao-core,实现自动装配
在gupao的pom.xml中引入组件的依赖。
<dependency>
<groupId>com</groupId>
<artifactId>gupao-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
@SpringBootApplication
public class App {
public static void main(String[] args) {
ConfigurableApplicationContext ca = SpringApplication.run(App.class, args);
People bean = ca.getBean(People.class);
System.out.println(bean.say());
}
}
Console控制台打印
2019-09-03 20:17:25.146 INFO 4672 --- [ main] com.differ.demo5.App : No active profile set, falling back to default profiles: default
2019-09-03 20:17:25.979 INFO 4672 --- [ main] com.differ.demo5.App : Started App in 1.257 seconds (JVM running for 1.705)
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.differ.sb.People' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:346)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:337)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1123)
at com.differ.demo5.App.main(App.java:16)
报错原因: 由于组件加入了条件。 所以必须在主项目中加入相应的条件才不会报错。
在guapo项目中,新建一个类即可。
com.differ.demo5.Test