一、前言
从本节开始,会花较多篇幅去深入了解Spring IoC容器的初始化流程。整体串联的知识点会很多,包括IoC容器的实现、IoC容器的初始化、Bean定义扫描、Bean的生命周期、Spring的扩展机制BeanFactoryPostProcessor
和BeanPostProcessor
,坚持住!
二、IoC容器创建及初始化
IoC容器的初始化,通常指的就是其 refresh()方法执行的整个流程,refresh()方法是Spring的最核心入口方法,不过在了解这个方法前,我们先看看IoC容器刷新之前做了什么前置工作?
结合源码来看,假设我们采用注解驱动式开发,写了MyIocClient
这样一个启动类
@ComponentScan
public class MyIocClient {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyIocClient.class);
// 关闭 context
// context.close();
}
}
没错,就上面一行代码就完成了ApplicationContext
的创建及初始化;点进AnnotationConfigApplicationContext
的构造方法`,总共就三步,看似很简单,但每一步做的事情都很重要。
2.1 第一步: 准备ApplicationContext
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
/**
* Create a new AnnotationConfigApplicationContext that needs to be populated
* through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
*/
public AnnotationConfigApplicationContext() {
/*
* AnnotatedBeanDefinitionReader 的构造方法 向ioc容器导入几个注解驱动的基础BPP组件 以及 Bean定义的后置处理器
* 见 AnnotatedBeanDefinitionReader 构造函数里面的 AnnotationConfigUtils.registerAnnotationConfigProcessors(BeanDefinitionRegistry, null) 方法:
*
* ConfigurationClassPostProcessor、
* AutowiredAnnotationBeanPostProcessor、
* RequiredAnnotationBeanPostProcessor、
* CommonAnnotationBeanPostProcessor
* EventListenerMethodProcessor
*/
this.reader = new AnnotatedBeanDefinitionReader(this);
// Bean定义扫描过滤配置
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
/**
* Create a new AnnotationConfigApplicationContext with the given DefaultListableBeanFactory.
* @param beanFactory the DefaultListableBeanFactory instance to use for this context
*/
public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
super(beanFactory);
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
/**
* Create a new AnnotationConfigApplicationContext, deriving bean definitions
* from the given annotated classes and automatically refreshing the context.
* @param annotatedClasses one or more annotated classes,
* e.g. {@link Configuration @Configuration} classes
*/
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
// 父类 GenericApplicationContext 的构造方法,创建了DefaultListableBeanFactory;
// 无参构造函数里面通过 AnnotatedBeanDefinitionReader , 向Ioc容器导入了几个注解开发的基础BPP组件
this();
// 为启动类创建 beanDefinition 并注册
register(annotatedClasses);
refresh();
}
}
一开始调用自身的无参构造方法,这里隐含一个知识点「Java类调用自身无参构造方法时会先触发父类无参构造」。点进其父类GenericApplicationContext
无参构造,可以看到直接new了一个DefaultListableBeanFactory
, 其就是一个标准的完成度很高的IoC容器实现,后面Ioc容器刷新过程中到到的BeanFactory
都是这个一个东东
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
/**
* Create a new GenericApplicationContext.
* @see #registerBeanDefinition
* @see #refresh
*/
public GenericApplicationContext() {
// 这里就创建了 DefaultListableBeanFactory
this.beanFactory = new DefaultListableBeanFactory();
}
}
再退回到 AnnotationConfigApplicationContext
无参构造, 可以看到无参构造里面new出了两个对象, 这两个对象也比较重要:
AnnotatedBeanDefinitionReader
见名知意,就是在注解驱动开发中解析 BeanDefinitionClassPathBeanDefinitionScanner
进行ClassPath下的 BeanDefinition 扫描及注册
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
/**
* Create a new AnnotationConfigApplicationContext that needs to be populated
* through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
*/
public AnnotationConfigApplicationContext() {
/*
* AnnotatedBeanDefinitionReader 的构造方法 向ioc容器导入几个注解驱动的基础BPP组件 以及 Bean定义的后置处理器
* 见 AnnotatedBeanDefinitionReader 构造函数里面的 AnnotationConfigUtils.registerAnnotationConfigProcessors(BeanDefinitionRegistry, null) 方法:
*
* ConfigurationClassPostProcessor、
* AutowiredAnnotationBeanPostProcessor、
* RequiredAnnotationBeanPostProcessor、
* CommonAnnotationBeanPostProcessor
* EventListenerMethodProcessor
*/
this.reader = new AnnotatedBeanDefinitionReader(this);
// Bean定义扫描过滤配置
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
}
这里有必要强调下,AnnotatedBeanDefinitionReader
这家伙的构造方法不仅仅只是为了new一个对象出来,还顺带为IoC容器导入了几个组件,具体可分为以下几种
- 导入修改Bean定义的BeanFacotroyPostProcess组件
ConfigurationClassPostProcessor
: 用来处理 @Configuration 注解
- 导入依赖注入的BeanPostProcess组件
AutowiredAnnotationBeanPostProcessor
: 用来处理 @Autowired 注解RequiredAnnotationBeanPostProcessor
: 用来处理 @Required 注解CommonAnnotationBeanPostProcessor
: 用来处理 @Resource、@PostConstruct、@PreDestroy 注解
- 导入Jpa组件
PersistenceAnnotationBeanPostProcessor
- 导入Spring事件监听组件
EventListenerMethodProcessor
DefaultEventListenerFactory
导入组件的具体代码见 AnnotatedBeanDefinitionReader
类
public class AnnotationConfigUtils {
/**
* 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, 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<BeanDefinitionHolder>(8);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
// 重要: BeanDefinition 的后置处理器
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));
}
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// 重要: 处理 @Resource @PostConstruct @PreDestroy 注解的BPP
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));
}
// EventListenerMethodProcessor.getEventListenerFactories() 这个方法会用到
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;
}
}
ClassPathBeanDefinitionScanner
这个对象的职责比较单一,就是为了后续扫描进行ClassPath下带有 @Componnent注解的类,进而解析注册 BeanDefinition; (注:@Service、@Repository、@Controller 这些注解其实都叠加了 @Componnent 注解,也是能被扫描到的)
至此,第一步就粗略过完了。一个this()方法就引出了这么一长串,Spring封装做得也真够了!
2.2 第二步: 注册启动类Bean定义
第二步就比较简单了, 直接为启动类创建Bean定义AnnotatedGenericBeanDefinition
, 并完成注册。启动类啥业务逻辑都没有,为什么需要注册呢?其实注册的目前是为了做ClassPath下面的Bean定义扫描,IoC容器是需要我们告知从哪些路径开始扫描的。
还记得启动类上的 @ComponentScan
注解吗, 通过启动类这个载体,IoC容器知道了扫描的起点是什么,顺腾摸瓜最终就就能完成扫描。特别低,我们的启动类上@ComponentScan
注解并未显示指定任何属性,Spring这时候的做法就是把启动类所在的包名,当做扫描的根起点。这个机制就能解释为什么往往会把启动类单独放在最外一层的包上面。
public class AnnotatedBeanDefinitionReader {
private final BeanDefinitionRegistry registry;
private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
private ConditionEvaluator conditionEvaluator;
/**
* Register a bean from the given bean class, deriving its metadata from
* class-declared annotations.
* @param annotatedClass the class of the bean
*/
@SuppressWarnings("unchecked")
public void registerBean(Class<?> annotatedClass) {
registerBean(annotatedClass, null, (Class<? extends Annotation>[]) null);
}
/**
* Register a bean from the given bean class, deriving its metadata from
* class-declared annotations.
* @param annotatedClass the class of the bean
* @param name an explicit name for the bean
* @param qualifiers specific qualifier annotations to consider,
* in addition to qualifiers at the bean class level
*/
@SuppressWarnings("unchecked")
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 解析 Lazy、Primary、DependsOn、Role、Description 属性
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 导入bean定义
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
2.3 第三步: 初始化Ioc容器
refresh()
方法是Ioc容器初始化的起点,实现逻辑在抽象类 AbstractApplicationContext
,整个方法细分为十二步,妥妥滴模板方法设计模式。后续会开文逐个步骤讲解,这里先混个脸熟,了解下IoC容器初始化的全貌;特别重要的两步是 invokeBeanFactoryPostProcessors(beanFactory)
和 finishBeanFactoryInitialization(beanFactory);
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
/*
* 这里获取到的BeanFactory是 DefaultListableBeanFactory,
* 它不是这里创建的, 而是在这之前的 GenericApplicationContext 的构造函数里面new出来的
*/
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
/*
* 对DefaultListableBeanFactory 做一些准备工作: 比如配置ClassLoader 、导入BPP组件
*/
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
/**
* 核心步骤:加载Bean定义;
* 调用BeanFactoryPostProcessor,会触发getBean操作; 这里用到的两个BPP都是在 prepareBeanFactory() 阶段导入的
*/
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
/*
* 注册bean的后置处理器
*/
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
/**
* 核心步骤:bean实例化、初始化
*/
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
三、小结
-
Spring IoC容器创建及初始化分三步
-
IoC容器初始化的前置准备工作分两块:
-
创建
AnnotatedBeanDefinitionReader
并导入系列组件 -
创建并配置
ClassPathBeanDefinitionScanner
后续用来进行ClassPath下的Bean定义扫描注册
-