通过Spring上下文初始化bean
注解类 ,AnnotationConfigApplicationContext可以实现基于java配置类(各种注解)来加载Spring上下文,相比于用application.xml更简洁更方便。
package com.jingjing.spring;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
/**
* 需要扫描哪些目录下的bean
* Created by jingjing on 2020/3/7
*/
@ComponentScan("com.jingjing")
public class Test {
public static void main(String[] args) {
/**
* 初始化bean init
* 1.把类扫描出来
* 2.把bean实例化
*/
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Test.class);
BeanTest beanTest= context.getBean(BeanTest.class);
System.out.println(beanTest);
}
}
package com.jingjing.spring;
import org.springframework.stereotype.Component;
/**
* Created by jingjing on 2020/3/7
*/
@Component
public class BeanTest{
public BeanTest() {
System.out.println("init");
}
}
AnnotationConfigApplicationContext构造函数
/**
* 将相应配置类中的bean注册到容器中
* 创建一个新的注解配置上下文,从annotatedClasses配置类中得到bean definitions,再将
* bean definition更新到上下文
* 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) {
//由于它有父类,会先调用父类构造方法,再调用自己的构造方法
//在自己的构造方法中初始化一个读取器和一个扫描器
//父类构造方法创建一个beanFactory DefaultListableBeanFactory
this();
//把注解类变成一个BeanDefinition
register(annotatedClasses);
//扫描类,并把这些路径下的Class变成一个BeanDefinition,再把部分BeanDefinition变成bean对象
refresh();
}
this()方法解析
AnnotationConfigApplicationContext继承于GenericApplicationContext
/**
* 父类GenericApplication默认构造函数,创建一个BeanFactory
* DefaultListableBeanFactory,一个很重要的BeanFactory
* Create a new GenericApplicationContext.
* @see #registerBeanDefinition
* @see #refresh
*/
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
/**
* 默认构造函数
* 创建一个基于注解的BeanDefinition读取器
* 创建一个通过路径扫描BeanDefinition扫描器
* Create a new AnnotationConfigApplicationContext that needs to be populated
* through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
*/
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
register(annotatedClasses)方法解析
/**
*实际上是调用AnnotatedBeanDefinitionReader类的register方法
*/
public void register(Class>... annotatedClasses) {
Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
this.reader.register(annotatedClasses);
}
核心逻辑是AnnotatedBeanDefinition的doRegisterBean()方法
public void register(Class>... annotatedClasses) {
Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
this.reader.register(annotatedClasses);
}
public void registerBean(Class> annotatedClass) {
doRegisterBean(annotatedClass, null, null, null);
}
/**
* Register a bean from the given bean class, deriving its metadata from
* class-declared annotations.
* @param annotatedClass the class of the bean
* @param instanceSupplier a callback for creating an instance of the bean
* (may be {@code null})
* @param name an explicit name for the bean
* @param qualifiers specific qualifier annotations to consider, if any,
* in addition to qualifiers at the bean class level
* @param definitionCustomizers one or more callbacks for customizing the
* factory's {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
* @since 5.0
*/
void doRegisterBean(Class annotatedClass, @Nullable Supplier instanceSupplier, @Nullable String name,
@Nullable Class extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//将配置类class转变成AnnotatedGenericBeanDefinition,AnnotatedGenericBeanDefinition继承BeanDefinition,
//作用是定义一个bean的数据结构,getmetadata()可以获取到该bean上的注解信息
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
//@Conditional装配条件判断是否跳过注册
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
//设置回调
abd.setInstanceSupplier(instanceSupplier);
//解析bean作用域(单例或原型),如果有@Scope注解就解析bean作用域,没有就默认singleton
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
//作用域写回beandefinition中
abd.setScope(scopeMetadata.getScopeName());
//生成bean配置类beanName
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//通用注解解析到BeanDefinition结构中,主要处理 lazy Primary DependsOn Role Description这五个注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
//@Qualifier特殊限定符处理
if (qualifiers != null) {
for (Class extends Annotation> qualifier : qualifiers) {
//如果配置Primary注解,则设置当前bean为自动装配autowire时首选bean
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
//设置懒加载即延时加载
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
//将其他注解添加到abd结构中
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
//自定义bean注册,通常用在applicationContext创建后,自己手动像容器中-lambda表达式的方式注册bean
// applicationContext.registerBean(Test.class,()->new Test());
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
//自定义bean添加到BeanDefinition
customizer.customize(abd);
}
//根据beanName beanDefinition(bean定义信息)封装成一个beanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
//创建代理对象
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//深入代码内部可以发现最后还是调用DefaultListableBeanFactory的registerBeanDefinition()
//逻辑是把 beanName,beanDefinition放入BeanFactory的BeanDefinitionMap中
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
其实register方法主要完成了配置类的解析和注册,主要有以下步骤
1.将配置类annotatedClass,使用BeanDefinition解析Bean的定义信息 ,主要是一些注解信息
2.bean的作用域处理,如果有@Scope作用域就返回作用域,没有就默认为Singleton
3.借助AnnotationConfigUtils解析通用注解
4.将bean定义信息(beanName,BeanDefinition)注册到Ioc容器中
refresh方法解析
refresh()方法在AbstractApplicationContext类中实现,这个类的主要作用就是加载或者刷新当前的配置信息,如果已经存在Spring容器则先销毁之前Spring容器,重新创建Spring容器,载入bean定义,完成容器初始化工作。可以看出AnnotationConfigApplicationContext容器是通过调用其父类AbstractApplicationContext的refresh方法启动整个Ioc容器完成对bean定义的载入和初始化
1.刷新预处理
AbstractApplicationContext.prepareRefresh()
protected void prepareRefresh() {
// Switch to active.
//设置容器启动时间
this.startupDate = System.currentTimeMillis();
//启动标识
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment.
//空方法,用于子容器自定义个性化的属性设置方法
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
//检验属性的合法等
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
// 保存预刷新的容器的早期监听器
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
//保存容器中的早期事件
this.earlyApplicationEvents = new LinkedHashSet<>();
}
2.子类刷新内部的BeanFactory并获得刷新的BeanFactory
AbstractApplicationContext.obtainBeanFactory()
/**
* 告诉子类刷新内部的BeanFactory
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
GenericApplicationContext.refreshBeanFactory和getBeanFactory
protected final void refreshBeanFactory() throws IllegalStateException {
//用AtomicBoolean的原子操作给refreshed变量赋值,初始化时refreshed是false,如果赋值失败抛出异常,避免多次刷新
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
//给BeanFactory设置序列化id为AnnotationConfigApplicationContext的id唯一标识
this.beanFactory.setSerializationId(getId());
}
public final ConfigurableListableBeanFactory getBeanFactory() {
//返回DefaultListableBeanFactory
return this.beanFactory;
}
刷新BeanFactory的步骤主要如下:
1.给AnnotationConfigApplicationContext的refreshed值设为true
2.给DefaultBeanFactory的serializationId设置值为AnnotationConfigApplicationContext的id值
3.BeanFactory预处理
主要完成BeanFactory的属性设置
/**
* 完成BeanFactory的属性设置
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
//给BeanFactory设置bean类加载器为容器的类加载器
beanFactory.setBeanClassLoader(getClassLoader());
//bean表达式解析器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//属性编辑注册器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
//使用上下文回调配置beanFactory
//添加一个BeanPostProcessor bean后置处理器实现ApplicationContextAwareProcess
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//设置忽略的自动装配接口,表示这些接口的实现类不能通过接口自动注入
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
//注册可以自动装配的组件,在任何组件中允许自动注入的组件
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
// 用应用监听器注册早期的PostProcessor 去检测内部的bean
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
//添加编译时的AspectJ
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
//给容器中注册Singleton组件,ConfigurableEnviroment,systemProperties,systemEnvironment,添加到singletonObjects(ConcurrentHashMap类型)中
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
5.执行BeanFactoryPostProcess方法,BeanFactory的后置处理器,在beanFactory标准初始化后执行
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List regularPostProcessors = new ArrayList<>();
List registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List priorityOrderedPostProcessors = new ArrayList<>();
List orderedPostProcessorNames = new ArrayList<>();
List nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}