“Spring Boot 2 自动配置流程”的版本间的差异
Jihongchang(讨论 | 贡献) (建立内容为“https://www.bilibili.com/video/BV19K4y1L7MT?p=15”的新页面) |
Jihongchang(讨论 | 贡献) |
||
(未显示同一用户的9个中间版本) | |||
第1行: | 第1行: | ||
https://www.bilibili.com/video/BV19K4y1L7MT?p=15 | https://www.bilibili.com/video/BV19K4y1L7MT?p=15 | ||
+ | |||
+ | === 以 AopAutoConfiguration 为例分析自动配置类 === | ||
+ | |||
+ | |||
+ | 以 spring-boot-autoconfigure-2.3.4.RELEASE.jar 中的 org.springframework.boot.autoconfigure.aop.AopAutoConfiguration 为例,分析自动配置流程 | ||
+ | |||
+ | spring-boot-autoconfigure-2.3.4.RELEASE.jar\META-INF\spring.factories<syntaxhighlight lang="properties"> | ||
+ | …… | ||
+ | # Auto Configure | ||
+ | …… | ||
+ | org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ | ||
+ | …… | ||
+ | </syntaxhighlight><syntaxhighlight lang="java"> | ||
+ | package org.springframework.boot.autoconfigure.aop; | ||
+ | |||
+ | import org.aspectj.weaver.Advice; | ||
+ | |||
+ | …… | ||
+ | @Configuration(proxyBeanMethods = false) | ||
+ | @ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true) | ||
+ | public class AopAutoConfiguration { | ||
+ | |||
+ | @Configuration(proxyBeanMethods = false) | ||
+ | @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) | ||
+ | @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); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | <code>@Configuration</code> 说明这是一个配置类; | ||
+ | |||
+ | <code>@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)</code> | ||
+ | |||
+ | 配置文件中是否存在 <code>spring.aop</code> 这个配置,如果存在了 <code>spring.aop.auto</code> 这个配置,并且它的值是“true”,那么这个类中的其他配置就生效,<code>matchIfMissing = true</code> 就算没有响应的配置,也认为满足条件,所以相当于这个配置是生效的 | ||
+ | |||
+ | 再来看<syntaxhighlight lang="java"> | ||
+ | @Configuration(proxyBeanMethods = false) | ||
+ | @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 { | ||
+ | |||
+ | } | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight><code>@Configuration</code> 说明这是一个配置类; | ||
+ | |||
+ | <code>@ConditionalOnClass(Advice.class)</code> 类路径中是否存在 <code>org.aspectj.weaver.Advice</code> 这个类,在 IDEA 中 按两下 Shift 只有选择 Classes tab 页,没有 <code>org.aspectj.weaver.Advice</code>这个类,所以这个类中的其他配置也就不生效了 | ||
+ | |||
+ | |||
+ | 接着再来看<syntaxhighlight lang="java"> | ||
+ | @Configuration(proxyBeanMethods = false) | ||
+ | @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); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight><code>@Configuration</code> 说明这是一个配置类; | ||
+ | |||
+ | <code>@ConditionalOnMissingClass("org.aspectj.weaver.Advice")</code> 当系统中没有 <code>org.aspectj.weaver.Advice</code> 这个类的时候生效; | ||
+ | |||
+ | <code>@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)</code> 配置文件中是不是配置了 <code>spring.aop.proxy-target-class=true</code>,没配也当配了生效; | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | === 以 CacheAutoConfiguration 为例分析自动配置类 === | ||
+ | spring-boot-autoconfigure-2.3.4.RELEASE.jar\META-INF\spring.factories<syntaxhighlight lang="properties"> | ||
+ | …… | ||
+ | # Auto Configure | ||
+ | …… | ||
+ | org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ | ||
+ | …… | ||
+ | </syntaxhighlight><syntaxhighlight lang="java"> | ||
+ | |||
+ | package org.springframework.boot.autoconfigure.cache; | ||
+ | |||
+ | …… | ||
+ | import org.springframework.cache.CacheManager; | ||
+ | …… | ||
+ | |||
+ | @Configuration(proxyBeanMethods = false) | ||
+ | @ConditionalOnClass(CacheManager.class) | ||
+ | @ConditionalOnBean(CacheAspectSupport.class) | ||
+ | @ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver") | ||
+ | @EnableConfigurationProperties(CacheProperties.class) | ||
+ | @AutoConfigureAfter({ CouchbaseDataAutoConfiguration.class, HazelcastAutoConfiguration.class, | ||
+ | HibernateJpaAutoConfiguration.class, RedisAutoConfiguration.class }) | ||
+ | @Import({ CacheConfigurationImportSelector.class, CacheManagerEntityManagerFactoryDependsOnPostProcessor.class }) | ||
+ | public class CacheAutoConfiguration { | ||
+ | |||
+ | …… | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight><code>@ConditionalOnClass(CacheManager.class)</code> 类路径中有,是 spring-context-5.2.9.RELEASE.jar 中的包,所以这个条件是成立的<code>@ConditionalOnBean(CacheAspectSupport.class)</code> 判断容器中是否存在 CacheAspectSupport 类型的组件:<syntaxhighlight lang="java"> | ||
+ | @SpringBootApplication(scanBasePackages = "io.github.jihch") | ||
+ | public class MainApplication { | ||
+ | |||
+ | public static void main(String[] args) { | ||
+ | //1、返回 IOC 容器 | ||
+ | ConfigurableApplicationContext context = SpringApplication.run(MainApplication.class, args); | ||
+ | |||
+ | //2、查看容器里面的组件 | ||
+ | String[] beanDefinitionNames = context.getBeanDefinitionNames(); | ||
+ | Arrays.sort(beanDefinitionNames); | ||
+ | for (String name : beanDefinitionNames) { | ||
+ | System.out.println(name); | ||
+ | } | ||
+ | |||
+ | int beanDefinitionCount = context.getBeanDefinitionCount(); | ||
+ | System.out.printf("beanDefinitionCount:%d\n", beanDefinitionCount); | ||
+ | |||
+ | String[] beanNamesForType = context.getBeanNamesForType(CacheAspectSupport.class); | ||
+ | System.out.printf("beanNamesForType.length:%d\n", beanNamesForType.length); | ||
+ | for (String s : beanNamesForType) { | ||
+ | System.out.println(s); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight><syntaxhighlight lang="console"> | ||
+ | …… | ||
+ | beanDefinitionCount:129 | ||
+ | beanNamesForType.length:0 | ||
+ | </syntaxhighlight>容器中没有 CacheAspectSupport 类型的组件,条件不成立,所以这个类中的其他 <code>@Bean</code> 的配置就不会生效 | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | === 以 DispatcherServletAutoConfiguration 为例分析自动配置类 === | ||
+ | spring-boot-autoconfigure-2.3.4.RELEASE.jar 中的 org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration<syntaxhighlight lang="java"> | ||
+ | package org.springframework.boot.autoconfigure.web.servlet; | ||
+ | …… | ||
+ | @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) | ||
+ | @Configuration(proxyBeanMethods = false) | ||
+ | @ConditionalOnWebApplication(type = Type.SERVLET) | ||
+ | @ConditionalOnClass(DispatcherServlet.class) | ||
+ | @AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class) | ||
+ | public class DispatcherServletAutoConfiguration { | ||
+ | …… | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> |
2023年3月5日 (日) 09:33的最新版本
https://www.bilibili.com/video/BV19K4y1L7MT?p=15
以 AopAutoConfiguration 为例分析自动配置类
以 spring-boot-autoconfigure-2.3.4.RELEASE.jar 中的 org.springframework.boot.autoconfigure.aop.AopAutoConfiguration 为例,分析自动配置流程
spring-boot-autoconfigure-2.3.4.RELEASE.jar\META-INF\spring.factories
……
# Auto Configure
……
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
……
package org.springframework.boot.autoconfigure.aop;
import org.aspectj.weaver.Advice;
……
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@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)
@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);
}
}
}
}
@Configuration
说明这是一个配置类;
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
配置文件中是否存在 spring.aop
这个配置,如果存在了 spring.aop.auto
这个配置,并且它的值是“true”,那么这个类中的其他配置就生效,matchIfMissing = true
就算没有响应的配置,也认为满足条件,所以相当于这个配置是生效的
再来看
@Configuration(proxyBeanMethods = false)
@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
说明这是一个配置类;
@ConditionalOnClass(Advice.class)
类路径中是否存在 org.aspectj.weaver.Advice
这个类,在 IDEA 中 按两下 Shift 只有选择 Classes tab 页,没有 org.aspectj.weaver.Advice
这个类,所以这个类中的其他配置也就不生效了
接着再来看
@Configuration(proxyBeanMethods = false)
@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);
}
}
}
@Configuration
说明这是一个配置类;
@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
当系统中没有 org.aspectj.weaver.Advice
这个类的时候生效;
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
配置文件中是不是配置了 spring.aop.proxy-target-class=true
,没配也当配了生效;
以 CacheAutoConfiguration 为例分析自动配置类
spring-boot-autoconfigure-2.3.4.RELEASE.jar\META-INF\spring.factories
……
# Auto Configure
……
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
……
package org.springframework.boot.autoconfigure.cache;
……
import org.springframework.cache.CacheManager;
……
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(CacheManager.class)
@ConditionalOnBean(CacheAspectSupport.class)
@ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver")
@EnableConfigurationProperties(CacheProperties.class)
@AutoConfigureAfter({ CouchbaseDataAutoConfiguration.class, HazelcastAutoConfiguration.class,
HibernateJpaAutoConfiguration.class, RedisAutoConfiguration.class })
@Import({ CacheConfigurationImportSelector.class, CacheManagerEntityManagerFactoryDependsOnPostProcessor.class })
public class CacheAutoConfiguration {
……
}
@ConditionalOnClass(CacheManager.class)
类路径中有,是 spring-context-5.2.9.RELEASE.jar 中的包,所以这个条件是成立的@ConditionalOnBean(CacheAspectSupport.class)
判断容器中是否存在 CacheAspectSupport 类型的组件:
@SpringBootApplication(scanBasePackages = "io.github.jihch")
public class MainApplication {
public static void main(String[] args) {
//1、返回 IOC 容器
ConfigurableApplicationContext context = SpringApplication.run(MainApplication.class, args);
//2、查看容器里面的组件
String[] beanDefinitionNames = context.getBeanDefinitionNames();
Arrays.sort(beanDefinitionNames);
for (String name : beanDefinitionNames) {
System.out.println(name);
}
int beanDefinitionCount = context.getBeanDefinitionCount();
System.out.printf("beanDefinitionCount:%d\n", beanDefinitionCount);
String[] beanNamesForType = context.getBeanNamesForType(CacheAspectSupport.class);
System.out.printf("beanNamesForType.length:%d\n", beanNamesForType.length);
for (String s : beanNamesForType) {
System.out.println(s);
}
}
}
……
beanDefinitionCount:129
beanNamesForType.length:0
容器中没有 CacheAspectSupport 类型的组件,条件不成立,所以这个类中的其他 @Bean
的配置就不会生效
以 DispatcherServletAutoConfiguration 为例分析自动配置类
spring-boot-autoconfigure-2.3.4.RELEASE.jar 中的 org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
package org.springframework.boot.autoconfigure.web.servlet;
……
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {
……
}