1. 背景介绍
启动一个基于 Spring 注解的容器,仅仅需要 new AnnotationConfigApplicationContext()
,并传入自己的配置类。这短短一句话,威力却很大。我们就从这句话开始探索,它到底干了些什么
public class MainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigSwitch.class);
}
}
AnnotationConfigApplicationContext 继承结构
2. 学习目标
- 了解 AnnotationConfigApplicationContext 及其父类实例化过程中做了哪些操作
- 了解 AnnotationConfigApplicationContext 及其父类的主要作用
- 明白 ApplicationContext 与 BeanFactory 的区别
3. 关键问题
- Environment 是什么时候注入 Spring 容器的
4. 源码追踪
AnnotationConfigApplicationContext
AnnotationConfigApplicationContext 及其父类
DefaultResourceLoader
↑
AbstractApplicationContext
↑
GenericApplicationContext
↑
AnnotationConfigApplicationContext
当执行 new AnnotationConfigApplicationContext(Class<?>... componentClasses)
之前,会先执行父类的无参构造方法
- AbstractApplicationContext 初始化了 PathMatchingResourcePatternResolver
- GenericApplicationContext 初始化了最为重要的 DefaultListableBeanFactory
执行 new AnnotationConfigApplicationContext(Class<?>... componentClasses)
-
this()
初始化 AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner -
register(componentClasses)
实际是调用了AnnotatedBeanDefinitionReader.register(Class<?>... componentClasses)
,请参考【Spring Cooking】厨师就位(二)AnnotatedBeanDefinitionReader注册配置类 -
refresh()
创建实例化对象
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
public AnnotationConfigApplicationContext() {
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
this.reader = new AnnotatedBeanDefinitionReader(this);
createAnnotatedBeanDefReader.end();
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
@Override
public void register(Class<?>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register")
.tag("classes", () -> Arrays.toString(componentClasses));
this.reader.register(componentClasses);
registerComponentClass.end();
}
}
AnnotatedBeanDefinitionReader
-
AnnotatedBeanDefinitionReader 属性初始化
AnnotationBeanNameGenerator
AnnotationScopeMetadataResolver -
执行有参构造
-
getOrCreateEnvironment(registry) 触发
AbstractApplicationContext.createEnvironment()
-
初始化ConditionEvaluator,用来解析 @Conditional 注解
-
调用 AnnotationConfigUtils.registerAnnotationConfigProcessors 注册相关注解的后置处理器
-
public class AnnotatedBeanDefinitionReader {
private final BeanDefinitionRegistry registry;
private BeanNameGenerator beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
private ConditionEvaluator conditionEvaluator;
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry instanceof EnvironmentCapable) {
return ((EnvironmentCapable) registry).getEnvironment();
}
return new StandardEnvironment();
}
}
AnnotationConfigUtils
-
查看 beanFactory.dependencyComparator 是否为 AnnotationAwareOrderComparator,不是的话则替换为 AnnotationAwareOrderComparator
-
查看 beanFactory.autowireCandidateResolver是否为 ContextAnnotationAutowireCandidateResolver,不是的话则替换为 ContextAnnotationAutowireCandidateResolver。此前为SimpleAutowireCandidateResolver,因此需要替换 ContextAnnotationAutowireCandidateResolver
-
注册五个内部组件的 BeanDefinition
beanName beanClass org.springframework.context.annotation.internalConfigurationAnnotationProcessor ConfigurationClassPostProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor AutowiredAnnotationBeanPostProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor CommonAnnotationBeanPostProcessor org.springframework.context.event.internalEventListenerProcessor EventListenerMethodProcessor org.springframework.context.event.internalEventListenerFactory DefaultEventListenerFactory 注册流程:
-
new RootBeanDefinition(Class<?> beanClass)
-
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE)
name value description ROLE_APPLICATION 0 Role hint indicating that a BeanDefinition is a major part of the application. Typically corresponds to a user-defined bean. ROLE_SUPPORT 1 Role hint indicating that a BeanDefinition is a supporting part of some larger configuration, typically an outer org.springframework.beans.factory.parsing.ComponentDefinition. SUPPORT beans are considered important enough to be aware of when looking more closely at a particular org.springframework.beans.factory.parsing.ComponentDefinition, but not when looking at the overall configuration of an application. ROLE_INFRASTRUCTURE 2 Role hint indicating that a BeanDefinition is a major part of the application. Typically corresponds to a user-defined bean. -
BeanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition)
beanName作为key,beanDefinition作为value,添加到DefaultListableBeanFactory.beanDefinitionMap, 并返回 BeanDefinitionHolder
-
将 BeanDefinitionHolder 添加到集合中
-
public abstract class AnnotationConfigUtils {
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null);
}
/**
* Register all relevant annotation post processors in the given registry.
* @param registry the registry to operate on
* @param source the configuration source element (already extracted)
* that this registration was triggered from. May be {@code null}.
* @return a Set of BeanDefinitionHolders, containing all bean definitions
* that have actually been registered by this call
*/
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
}
ClassPathBeanDefinitionScanner
ClassPathBeanDefinitionScanner 构造方法调用了 registerDefaultFilters,往 includeFilters 添加
- AnnotationTypeFilter(Component.class)
- AnnotationTypeFilter(javax.annotation.ManagedBean)
- AnnotationTypeFilter(javax.inject.Named)
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
private final BeanDefinitionRegistry registry;
private BeanDefinitionDefaults beanDefinitionDefaults = new BeanDefinitionDefaults();
@Nullable
private String[] autowireCandidatePatterns;
private BeanNameGenerator beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
private boolean includeAnnotationConfig = true;
/**
* Create a new {@code ClassPathBeanDefinitionScanner} for the given bean factory.
* @param registry the {@code BeanFactory} to load bean definitions into, in the form
* of a {@code BeanDefinitionRegistry}
*/
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
this(registry, true);
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment) {
this(registry, useDefaultFilters, environment,
(registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
if (useDefaultFilters) {
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
}
public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
protected void registerDefaultFilters() {
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
}
GenericApplicationContext
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
}
DefaultListableBeanFactory
以下是 DefaultListableBeanFactory 及其父类的无参构造和属性
其中 AbstractAutowireCapableBeanFactory 初始化了 DefaultParameterNameDiscoverer 和 CglibSubclassingInstantiationStrategy
DefaultListableBeanFactory 赋值 SimpleAutowireCandidateResolver
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
/** Resolver to use for checking if a bean definition is an autowire candidate. */
private AutowireCandidateResolver autowireCandidateResolver = SimpleAutowireCandidateResolver.INSTANCE;
public DefaultListableBeanFactory() {
super();
}
}
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
/** Strategy for creating bean instances. */
private InstantiationStrategy instantiationStrategy;
/** Resolver strategy for method parameter names. */
@Nullable
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
/**
* Dependency interfaces to ignore on dependency check and autowire, as Set of
* Class objects. By default, only the BeanFactory interface is ignored.
*/
private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<>();
public AbstractAutowireCapableBeanFactory() {
super();
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
if (NativeDetector.inNativeImage()) {
this.instantiationStrategy = new SimpleInstantiationStrategy();
}
else {
this.instantiationStrategy = new CglibSubclassingInstantiationStrategy();
}
}
public void ignoreDependencyInterface(Class<?> ifc) {
this.ignoredDependencyInterfaces.add(ifc);
}
}
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
/** ClassLoader to resolve bean class names with, if necessary. */
@Nullable
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
/** BeanPostProcessors to apply. */
private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();
public AbstractBeanFactory() {}
}
AbstractApplicationContext
AbstractApplicationContext 实现了 ConfigurableEnvironment 接口,通过 createEnvironment() 来创建一个 StandardEnvironment
另外 AbstractApplicationContext 继承了 DefaultResourceLoader,拥有了加载类路径资源的能力。可以看到无参构造实际上就是去初始化去初始化 resourcePatternResolver
,这里使用了装饰者模式 new PathMatchingResourcePatternResolver(this)
,实现了功能增强
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
public AbstractApplicationContext() {
this.resourcePatternResolver = getResourcePatternResolver();
}
protected ResourcePatternResolver getResourcePatternResolver() {
return new PathMatchingResourcePatternResolver(this);
}
@Override
public ConfigurableEnvironment getEnvironment() {
if (this.environment == null) {
this.environment = createEnvironment();
}
return this.environment;
}
protected ConfigurableEnvironment createEnvironment() {
return new StandardEnvironment();
}
}
PathMatchingResourcePatternResolver
这里用到了装饰者模式,可以看到 PathMatchingResourcePatternResolver 的有参构造所用的参数是其顶层接口 ResourceLoader ,类似 new BufferedInputStream(InputStream)
。
后续在 @ComponentScan 扫描的时候会调用 getResources(String locationPattern)
来获取 Class 文件
public class PathMatchingResourcePatternResolver implements ResourcePatternResolver {
public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
Assert.notNull(resourceLoader, "ResourceLoader must not be null");
this.resourceLoader = resourceLoader;
}
}
DefaultResourceLoader
public class DefaultResourceLoader implements ResourceLoader {
public DefaultResourceLoader() {}
}
5. 结论
先看学习目标是否达成
-
了解 AnnotationConfigApplicationContext 及其父类实例化过程中做了哪些操作
AbstractApplicationContext 实例化创建了 PathMatchingResourcePatternResolver
GenericApplicationContext 实例化创建了 DefaultListableBeanFactory
AnnotationConfigApplicationContext 实例化创建了 AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner
其中 AnnotatedBeanDefinitionReader 在实例化过程中触发了 Environment 的创建,并注册了五个重要内部组件的 BeanDefinition
-
了解 AnnotationConfigApplicationContext 及其父类的主要作用
AnnotationConfigApplicationContext
独立的ApplicationContext,可以注册 @Configuration,@Component和JSR-330规范注解的类
可以通过register(Class…)来注册Class,或者scan(String…)来扫描类路径
当前注册的BeanDefinition会被后续解析的@Configuration或者@Bean方法覆盖
GenericApplicationContext
继承自 AbstractApplicationContext,可以加载各种配置文件,例如xml,properties等等。
持有一个 DefaultListableBeanFactory 实例,并且在启动的时候已经准备好了。
refresh() 只被调用一次。与之相反的是 AbstractRefreshableApplicationContext
实现了 BeanDefinitionRegistry 接口,这样 BeanAnnotationReader 运用它来读取 BeanDefinition,像本篇文章的 AnnotatedBeanDefinitionReader ,还有后续会提及的 ConfigurationClassBeanDefinitionReader,XmlBeanDefinitionReader,PropertiesBeanDefinitionReader
典型的用法是通过 BeanDefinitionRegistry 接口注册各种bean定义,然后调用refresh() 来使用 ApplicationContext 语义初始化这些bean。
GenericApplicationContext ctx = new GenericApplicationContext(); XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx); xmlReader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml")); PropertiesBeanDefinitionReader propReader = new PropertiesBeanDefinitionReader(ctx); propReader.loadBeanDefinitions(new ClassPathResource("otherBeans.properties")); ctx.refresh(); MyBean myBean = (MyBean) ctx.getBean("myBean");
From chat with Bing
GenericApplicationContext 的优势是它可以灵活地使用不同的 bean 定义格式和资源位置,而不受限于标准的 XML 文件或注解。它也可以在一开始就获取到内部的 BeanFactory 实例,而不需要等待刷新操作。这样可以提高性能和灵活性。AbstractApplicationContext
ApplicationContext 接口的抽象实现类,使用的是模板方法设计模式,子类需要实现以下方法
void refreshBeanFactory()
void closeBeanFactory()
ConfigurableListableBeanFactory getBeanFactory()
与 BeanFactory 不同,ApplicationContext 应该可以检测其内部 BeanFactory 定义的特殊bean。要完成这项工作,则需要以下三个组件的加持
- BeanFactoryPostProcessors
- BeanPostProcessors
- ApplicationListeners
AbstractApplicationContext 还额外提供两个 bean
- MessageSource
- ApplicationEventMulticaster
继承 DefaultResourceLoader 来实现资源加载
DefaultResourceLoader
ResourceLoader 的默认实现,ResourceEditor 的成员变量
定位的资源如果是URL,则返回UrlResource;如果是非URL或者“classpath:”,则返回 ClassPathResource
-
明白 ApplicationContext 与 BeanFactory 的区别
6. 注意细节
7. 待研究
- PathMatchingResourcePatternResolver 是如何加载资源文件