文章目录
底层注解
@Configuration配置类
- @Configuration : 告诉SpringBoot这是一个配置类
- 配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
- 配置类本身也是组件
- proxyBeanMethods : 代理bean的方法
- Full(proxyBeanMethods = true)【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
- Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
- 组件依赖必须使用Full模式默认。其他默认是否Lite模式
- 配置类中的方法之间没有互相调用,用Lite模式,就将proxyBeanMethods = false,这样SpringBoot就不会每次启动都花时间检查容器中组件的依赖关系
- 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式(即如,某个对象可能需要用到另一个对象,这就叫存在依赖关系)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
@AliasFor(annotation = Component.class)
String value() default "";
/*
* 指定是否应代理@Bean方法以强制执行Bean生命周期行为,
* 例如,即使在用户代码中直接调用@Bean方法的
* 情况下,也返回共享的单例Bean实例。此功能需要方法拦截,
* 通过运行时生成的CGLIB子类实现,该子类有一些限制,例如不允许配置类及其方法声明final。
*
* 默认值为true,允许通过配置类内的直接方法调用进行“bean间引用”,
* 以及外部调用此配置的@bean方法,例如从另一个配置类进行调用。
* 如果由于此特定配置的@Bean方法都是自包含的,并且设计为容器使用的普通工厂方法,
* 因此不需要这样做,请将此标志切换为false,以避免CGLIB子类处理。
*/
boolean proxyBeanMethods() default true;
}
Configuration使用示例
/**
* 1.@Configuration : 告诉SpringBoot这是一个配置类
* 2.配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
* 3.配置类也是组件
* 4.proxyBeanMethods : 代理bean的方法
* Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
* Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
* 组件依赖必须使用Full模式默认。其他默认是否Lite模式
*/
@Configuration(proxyBeanMethods = true)
public class MyConfig {
/**
* @Bean : 给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
*
* Full模式:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
*
* @return User
*/
@Bean
public User getUser() {
User user = new User();
user.setAge(18);
user.setName("zhang");
// user组件依赖了Pets组件
user.setPets(getTomcat());
return user;
}
@Bean(name = "tom")
public Pets getTomcat() {
Pets pets = new Pets();
pets.setName("Tomcat");
return pets;
}
}
从容器中获取组件
/**
* 主程序类
* @SpringBootApplication : 这是一个SpringBoot应用
*/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
// 1.返回IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
// 2.查看容器里的组件
String[] beanDefinitionNames = run.getBeanDefinitionNames();
for (String name : beanDefinitionNames) {
System.out.println(name);
}
// 3.从容器了获取组件
User user1 = run.getBean("getUser", User.class);
User user2 = run.getBean("getUser", User.class);
System.out.println("组件:" + (user1 == user2)); // 组件:true 说明是单列的
// 4.com.kernel.boot.config.MyConfig$$EnhancerBySpringCGLIB$$eedda4d0@2577d6c8
MyConfig bean = run.getBean(MyConfig.class);
System.out.println(bean);
// 如果@Configuration(proxyBeanMethods = true) 代理对象调用方法,
// SpringBoot总会检查这个组件是否在容器中保持组件单列
// 总结:使用代理,容器实例唯一,不使用代理,多次调用多个实例
User user3 = bean.getUser();
User user4 = bean.getUser();
System.out.println(user3 == user4); // true
// 组件依赖
User user5 = run.getBean("getUser", User.class);
Pets tom = run.getBean("tom", Pets.class);
System.out.println("用户的宠物:"+(user5.getPets() == tom)); // 用户的宠物:true
}
}
容器中注册组件的其它注解
@Bean、@Component、@Controller、@Service、@Repository
@Import
@Configuration类可以使用@Import注解来进行组合,将多个配置类组合在一起。类似于SpringXML中<Import>的工作方式。@Configuration对象在容器中作为Spring bean进行管理,所以可以注入导入的配置,例如,通过构造函数注入:
@Configuration
public class DatabaseConfig {
@Bean
public DataSource dataSource() {
// instantiate, configure and return DataSource
}
}
@Configuration //类似总配置类
// 将DatabaseConfig 加进来
@Import(DatabaseConfig.class)
public class AppConfig {
private final DatabaseConfig dataConfig;
public AppConfig(DatabaseConfig dataConfig) {
this.dataConfig = dataConfig;
}
@Bean
public MyBean myBean() {
// reference the dataSource() bean method
return new MyBean(dataConfig.dataSource());
}
}
@Conditional条件装配
条件装配:满足Conditional指定的条件,则进行组件注入
条件装配示例@ConditionalOnBean
@Configuration
public class MyConfig {
@Bean
@ConditionalOnBean(name = "tom") // 当容器中有tom这个组件才进行注入
public User getUser() {
User user = new User();
user.setAge(18);
user.setName("zhang");
user.setPets(getTomcat());
return user;
}
public Pets getTomcat() {
Pets pets = new Pets();
pets.setName("Tomcat");
return pets;
}
}
/**
* 主程序类
* @SpringBootApplication : 这是一个SpringBoot应用
*/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
// 1.返回IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
// 2.查看容器里的组件
String[] beanDefinitionNames = run.getBeanDefinitionNames();
for (String name : beanDefinitionNames) {
System.out.println(name);
}
boolean tom = run.containsBean("tom");
System.out.println("容器中是否有tom组件" + tom); // 容器中是否有tom组件false
boolean getUser = run.containsBean("getUser");
System.out.println("容器中是否有getUser组件" + getUser); // 容器中是否有getUser组件false
}
}
@ImportResource
@ImportResource(“classpath:beans.xml”)用来导入指定的配置文件。
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="haha" class="com.kernel.boot.bean.User">
<property name="name" value="zhangsan"></property>
<property name="age" value="18"></property>
</bean>
<bean id="hehe" class="com.kernel.boot.bean.Pets">
<property name="name" value="tomcat"></property>
</bean>
</beans>
@Configuration
@ImportResource("classpath:beans.xml")
public class MyConfig {
@Bean(name = "tom")
public Pets getTomcat() {
Pets pets = new Pets();
pets.setName("Tomcat");
return pets;
}
}
测试
/**
* 主程序类
* @SpringBootApplication : 这是一个SpringBoot应用
*/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
// 1.返回IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
// 2.查看容器里的组件
String[] beanDefinitionNames = run.getBeanDefinitionNames();
boolean haha = run.containsBean("haha");
boolean hehe = run.containsBean("hehe");
System.out.println("haha:" + haha); // true
System.out.println("hehe:" + hehe); // true
}
}
@ConfigurationProperties
读取到properties文件中的内容,并且把它封装到JavaBean中,以供随时使用。
application.properties
car.brand=BYD
car.price=10000
Car
/**
* @ClassName Car
* @author: shouanzh
* @Description 只有在容器中的组件,才会拥有SpringBoot提供的强大功能
* @date 2022/4/7 23:44
*/
@Component
@ConfigurationProperties(prefix = "car") // prefix 指定前缀
//@PropertySource("classpath:app.properties") 指定配置文件
@Data
public class Car {
private String brand;
private Integer price;
}
测试
@RestController
public class HelloController {
@Autowired
private Car car;
@RequestMapping("/hello")
public String hello() {
System.out.println(car.getBrand()); // BYD
System.out.println(car.getPrice()); // 10000
return "Hello, Spring Boot 2!";
}
}
方式二
@ConfigurationProperties(prefix = "car") // prefix 指定前缀
@Data
public class Car {
private String brand;
private Integer price;
}
@Configuration
@EnableConfigurationProperties(Car.class)
//1、开启Car配置绑定功能
//2、把这个Car这个组件自动注册到容器中
public class MyConfig {
}
自动配置原理
核心注解:@SpringBootApplication
@SpringBootConfiguration
@Configuration : 代表当前是一个配置类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}
@ComponentScan
扫描路径,默认值扫描main的同级和下级路径,scan可以添加上级路径。
例如,如果类中用了@Controller,@Repository,@Service,@Component四大注解之一标识了,那么如果不加上@ComponentScan,Spring就不会自动扫描类上的四大注解中的任何一个,那么四大注解下的类就不会被Spring扫描到,更不会装入Spring容器中,因此你配置的四大注解就失去了作用。
@EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
可以看到@EnableAutoConfiguration由@AutoConfigurationPackage和@Import(AutoConfigurationImportSelector.class)合成。
@AutoConfigurationPackage
自动配置包:指定了默认的包规则
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class) // 导入组件
public @interface AutoConfigurationPackage {
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
我们看一下Registrar
利用Registrar给容器中导入一系列组件
将指定的一个包下的所有组件导入进来。MainApplication 所在包下。
@Import(AutoConfigurationImportSelector.class)
跟一下AutoConfigurationImportSelector源码
1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
2、调用List configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
3、利用工厂加载 Map<String, List> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件
4、从META-INF/spring.factories位置来加载一个文件。
默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories
文件里面写死了spring-boot一启动就要给容器中加载的所有配置类
spring-boot-autoconfigure-2.3.4.RELEASE.jar/META-INF/spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
按需开启自动配置项
虽然我们130个场景的所有自动配置启动的时候默认全部加载:xxxxAutoConfiguration。
按照条件装配规则(@Conditional),最终会按需配置。
我们来分析一下AOP自动配置是否生效
package org.springframework.boot.autoconfigure.aop;
import org.aspectj.weaver.Advice;
import org.springframework.aop.config.AopConfigUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
// 配置类
@Configuration(proxyBeanMethods = false)
// 配置文件是否存在 spring.aop.auto=true matchIfMissing = true:就算没配也按照true
// 说明AopAutoConfiguration生效
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
@Configuration(proxyBeanMethods = false) // 配置类
// 是否存在 org.aspectj.weaver.Advice;
// 不存在 不生效
@ConditionalOnClass(Advice.class)
static class AspectJAutoProxyingConfiguration {
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
matchIfMissing = false)
static class JdkDynamicAutoProxyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class CglibAutoProxyConfiguration {
}
}
@Configuration(proxyBeanMethods = false) // 配置类
// 判断系统里没有org.aspectj.weaver.Advice这个类就生效(目前确实没有)
// 所以经过分析开启简单的aop
@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class ClassProxyingConfiguration {
ClassProxyingConfiguration(BeanFactory beanFactory) {
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
}
}
}
SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先
@Bean
@ConditionalOnMissingBean // 没有这个组件,才注入
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));
return filter;
}
总结
- SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
- 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
- 生效的配置类就会给容器中装配很多组件
- 只要容器中有这些组件,相当于这些功能就有了
- 定制化配置
- 用户直接自己@Bean替换底层的组件
- 用户去看这个组件是获取的配置文件什么值就去修改。
xxxxxAutoConfiguration —> 按需加载组件 —> xxxxProperties里面拿值 ----> application.properties