一直在摸索spring框架,看了《Spring技术内幕》和《Spring源码深度解析》,而这两本书在讲Spring IOC容器的时候都是讲xml配置方式的,但我觉得基于注解的方式没有读取解析xml文件会更简单。
spring版本:4.3.18
本篇主要介绍一些重要的接口及类,下一篇介绍bean的创建过程,接着介绍AnnotationConfigApplicationContext的初始化流程,最后一篇通过源码总结bean的生命周期。
BeanDefinition
了解BeanDefinition是什么:
这是一个接口,从接口名称可以看出这是对bean定义的抽象。
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
//单例singleton
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
//原型prototype
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
//写入bean的类型
void setBeanClassName(String beanClassName);
//获取bean的类型
String getBeanClassName();
//写入scope(范围)即是否单例
void setScope(String scope);
//获取Scope
String getScope();
//设置是否懒初始化
void setLazyInit(boolean lazyInit);
//是否懒初始化(getBean的时候再初始化)
boolean isLazyInit();
//获取构造参数值
ConstructorArgumentValues getConstructorArgumentValues();
//获取属性值
MutablePropertyValues getPropertyValues();
//是否单例
boolean isSingleton();
//是否原型
boolean isPrototype();
//返回原始的BeanDefinition
BeanDefinition getOriginatingBeanDefinition();
/**
* 设置此bean初始化所依赖的bean的名称。
* bean工厂将确保这些bean首先被初始化。
*/
void setDependsOn(String... dependsOn);
/**
* 返回此bean所依赖的bean名称。
*/
String[] getDependsOn();
这是被我简化过的BeanDefinition源码。
spring在读取xml配置文件的时候,并不是将每一个直接解析生产一个实例,而是统一的将所有的都解析为一个BeanDefinition对象,最后不管是不是单例的getBean获取一个bean的时候都是通过BeanDefinition对象生成的对象。如果是单例的且非懒初始化那么bean在容器初始化的时候就被初始化存放到bean容器了,如果是单例且懒初始化那么会在用到的时候才会实例化且存入到bean容器中。基于注册也是一样的,被@Component等注解声明的类都会被解析为BeanDefinition存放在bean工厂,最后才根据BeanDefinition生成目标对象。
因为我要说的是基于注解方式的bean容器初始化过程,所以我只关注AnnotateGenericBeanDefinition,该类继承GenericBeanDefinition且实现了AnnotateBeanDefinition接口,GenericBeanDefinition是一个通过的BeanDefinition,AnnotateGenericBeanDefinition就只是多实现了一个AnnotateBeanDefinition接口。
public interface AnnotatedBeanDefinition extends BeanDefinition {
//获取这个beandefinition描述的类的注解元数据(描述注解的数据),理解为获取注解信息就好了。
AnnotationMetadata getMetadata();
//获取工厂方法信息
MethodMetadata getFactoryMethodMetadata();
}
ApplicationContext
ApplicationContext理解为应用上下文,实现了BeanFactory接口,是bean的管理者。ApplicationContext扩展了很多使用的功能,如Bean的生命周期管理、框架事件体系、国际化支持等。同时,ApplicationContext接口还通过继承其他接口扩展了BeanFactory的功能:
- MessageSource:为应用提供国际化访问功能
- ResourceLoader:提供资源(如URL和文件系统)的访问支持
- ApplicationEventPublisher:引入事件机制,包括启动事件、关闭事件等,让容器在上下文中提供了对应用事件的支持。
常用的ApplicationContext都是继承AbstractApplicationContext(不是直接继承就是父类或父类的父类继承了)。
重点关注的三个ApplicationContext:
- FileSystemXmlApplicationContext:根据文件路径加载xml配置文件启动ApplicationContext。
- ClassPathXmlApplicationContext:根据类路径加载xml文件启动ApplicationContext。
- AnnotationConfigApplicationContext:初始化一个支持注解的ApplicationContext。
AnnotationConfigApplicationContext的一个直接子类是GenericApplicationContext,所有继承自GenericApplicationContext的应用上下文都是通过内部持有一个DefaultListableBeanFactory实例实现工厂功能的,虽然ApplicationContext实现了BeanFactory接口。
AnnotationConfigApplicationContext实现了AnnotationConfigRegistry接口。可以将bean(被@Component等声明的类)直接注册到AnnotationConfigApplicationContext中,或者注册@Configuration声明的配置类,在配置类中以声明包扫描的方式或者使用@Bean来向容易中注入bean。
//注解配置应用程序上下文的通用接口
public interface AnnotationConfigRegistry {
//注册一个或多个要处理的带注释的类。
void register(Class<?>... annotatedClasses);
//扫描指定的一个或多个包
void scan(String... basePackages);
}
BeanFactory
public interface BeanFactory {
//注册实现FactoryBean接口的bean,如果想要获取FactoryBean本身则在bean名称前面添加“&”字符。
String FACTORY_BEAN_PREFIX = "&";
//返回指定bean的一个实例,bean不存在则创建
Object getBean(String name) throws BeansException;
/**
* 返回一个bean的实例,bean不存在则创建
* @param name bean的名称(id)
* @param requiredType 可以是bean实现的接口或者继承的父类
*/
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
/**
* 支持泛型方式获取bean,这样获取到bean的时候就不需要强制类型转换了
* 如果没有找到给定类型的bean,则抛出NoSuchBeanDefinitionException
* 如果无法创建bean,则抛出BeansException
* 如果指定的类型有多个bean则会抛出NoUniqueBeanDefinitionException异常
*/
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
/**
* 是否存在具有给定名称的bean
*/
boolean containsBean(String name);
/**
* 指定的bean是否是单例的
*/
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
/**
* 指定的bean是否是原型
*/
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
/**
* 检查具有给定名称的bean是否与指定的类型匹配。
*/
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
/**
* 确定具有给定名称的bean的类型。
*/
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
/**
* 获取bean的所有别名,如果不存在别名则返回空
*/
String[] getAliases(String name);
}
接着看一个BeanFactory接口的扩展接口ListableBeanFactory,前面说过AbstractApplicationContext是通过内部持有一个DefaultListableBeanFactory对象作为真正的bean工厂的,而AnnotationConfigApplicationContext也是AbstractApplicationContext的子类,这些后面再说。DefaultListableBeanFactory实现ConfigurableListableBeanFactory接口,ConfigurableListableBeanFactory接口又是ListableBeanFactory的扩展接口。
ListableBeanFactory接口源码,去掉了一些方法的定义。
public interface ListableBeanFactory extends BeanFactory {
/**
* 检查此bean工厂是否包含具有给定名称的BeanDefinition。
* 忽略通过BeanDefinition以外的其他方式注册的任何单例bean,
* 如:@Bean定义的
*/
boolean containsBeanDefinition(String beanName);
/**
* 获取BeanDefinition的总数
*/
int getBeanDefinitionCount();
/**
* 获取所有的BeanDefinition的名称
*/
String[] getBeanDefinitionNames();
......
String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
<T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
<T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
throws BeansException;
/**
* 获取所有被指定类型注解注释的bean的名称
*/
String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
/**
* 获取所有被指定类型的注解注释的bean
*/
Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;
/**
* 在bean中查找指定类型的注解
* @param beanName 要查找的注解的bean的名称
* @param annotationType 注解类型
*/
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
throws NoSuchBeanDefinitionException;
}
BeanFactoryPostProcessor
BeanFactory后置处理器,实现该接口的类,在@Configuration注解的配置类上添加
@Import({BeanFactoryPostProcessor实现类.class})
可将该类注册为一个bean,在bean工厂准备好之后(单例的bean还没有被实例化)调用,主要是用来自定义修改持有的bean的定义信息。
public interface BeanFactoryPostProcessor {
/**
* 在应用程序上下文的标准初始化之后修改其内部bean工厂。
* 所有bean定义都已经加载,但是还没有实例化bean。
* 这允许覆盖或添加属性,甚至可以初始化bean。
* @param beanFactory 应用程序上下文使用的bean工厂
*
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
ConfigurableListableBeanFactory是ListableBeanFactory接口的扩展,DefaultListableBeanFactory实现了该ConfigurableListableBeanFactory接口,而AnnotationConfigApplicationContext应用上下文使用的bean工厂是DefaultListableBeanFactory实例。所以这里的参数实际上就是DefaultListableBeanFactory实例。
//AnnotationConfigApplicationContext
public class AnnotationConfigApplicationContext
extends GenericApplicationContext
implements AnnotationConfigRegistry {
}
//GenericApplicationContext
public class GenericApplicationContext
extends AbstractApplicationContext
implements BeanDefinitionRegistry {
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
}
BeanFactoryPostProcessor的使用:
自定义MyBeanFactoryPostProcessor实现BeanFactoryPostProcessor接口。
public class MyBeanFactoryPostProcessor
implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory)
throws BeansException {
String[] names = beanFactory.getBeanDefinitionNames();
// 获取了所有的bean名称列表
for(int i=0; i<names.length; i++){
String name = names[i];
BeanDefinition bd = beanFactory.getBeanDefinition(name);
System.out.println(name + " bean properties: \n"
+ bd.getPropertyValues().toString());
}
}
}
在postProcessBeanFactory方法打印bean工厂中所有BeanDefinition的属性值信息(key=字段名,value=将要注入的值)。当然现在还不起作用,需要在被添加
@Import({MyBeanFactoryPostProcessor.class})
这样才会起作用。还有另一种,在new AnnotationConfigApplicationContext的时候给AnnotationConfigApplicationContext注册的配置类中的包扫描添加一个扫描MyBeanFactoryPostProcessor所在包的@ComponentScan注解。
@ComponentScans中添加一个
@ComponentScan("wjy.stu.dao")
在MyBeanFactoryPostProcessor类上添加@Configuration。最后还有一种就是可以直接在配置类中使用@Bean注册一个MyBeanFactoryPostProcessor的实例。
BeanPostProcessor
bean的后置处理器。前面BeanFactoryPostProcessor是BeanFactory的后置处理器,在bean工厂准备就绪单例bean还没有被初始化的时候被调用。bean的后置处理器则是在bean初始化前后被调用。注意,是容器中所有的bean在调用初始化方法前后都会调用这个BeanPostProcessor的postProcessBeforeInitialization方法和postProcessAfterInitialization方法。不管是单例的还是原型的,都会被应用到,如果不是单例的那么每次调用getBean都会根据BeanDefinition创建一个bean实例,在创建bean的过程中仍然会调用bean的初始化方法,所以也会调用BeanPostProcessor的方法。
public interface BeanPostProcessor {
/**
* 将这个BeanPostProcessor应用到给定的新bean实例 ,在bean调用初始化方法之前被调用。
* @param bean 新的bean实例
* @param beanName 这个bean的名称
* @return 返回参数传递过来的原始bean,或者在该方法中修改过之后的bean;
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/**
* 将这个BeanPostProcessor应用到给定的新bean实例 ,在bean调用初始化方法完成之后被调用。
* @param bean 新的bean实例
* @param beanName 这个bean的名称
* @return 返回参数传递过来的原始bean,或者在该方法中修改过之后的bean;
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
在bean初始化时调用初始化方法之前和调用初始化方法之后分别调用applyBeanPostProcessorsBeforeInitialization方法和applyBeanPostProcessorsAfterInitialization方法。
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
......
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}catch (Throwable ex) {
......
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
在这里提一下这个invokeInitMethods方法。
如果bean实现了InitializingBean接口,则会先调用该bean的afterPropertiesSet方法。
@Component
public class ScoreBean implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
}
}
如果该bean的BeanDefinition存在initMethod方法,比如@Bean注解声明的初始化方法:@Bean(initMethod = “init”)
当该bean没有实现InitializingBean接口的时候才会被调用,避免了调用多个初始化方法的情况。
protected void invokeInitMethods(String beanName,
final Object bean, RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean
&& "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
AnnotatedBeanDefinitionReader
负责将被注解声明的bean读取为一个BeanDefinition。这是ClassPathBeanDefinitionScanner的替代方法,它应用相同的注解解析,但仅适用于显式注册的类。显示注册就是直接调用AnnotationConfigApplicationContext的register方法注册的类,或者AnnotationConfigApplicationContext构造方法中传入的类。
同ClassPathBeanDefinitionScanner都是在AnnotationConfigApplicationContext的构造方法中被实例化。
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
调用AnnotationConfigApplicationContext的register方法实际上调用的是AnnotatedBeanDefinitionReader的register方法。
public void register(Class<?>... annotatedClasses) {
Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
this.reader.register(annotatedClasses);
}
在registerBean方法中通过要注册的类构造一个AnnotatedGenericBeanDefinition对象,这实际上是一个StandardAnnotationMetadata对象,后面再详细说名。通过ScopeMetadataResolver解析注册的类的Scope。给该BeanDefinition设置Scope。AnnotationConfigUtils.processCommonDefinitionAnnotations方法处理常用的定义注解。
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));
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);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
BeanDefinitionHolder:
BeanDefinitionHolder是BeanDefinition的持有者。
public class BeanDefinitionHolder implements BeanMetadataElement {
private final BeanDefinition beanDefinition;
private final String beanName;
private final String[] aliases;
public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName) {
this(beanDefinition, beanName, null);
}
public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName, String[] aliases) {
this.beanDefinition = beanDefinition;
this.beanName = beanName;
this.aliases = aliases;
}
public BeanDefinitionHolder(BeanDefinitionHolder beanDefinitionHolder) {
this.beanDefinition = beanDefinitionHolder.getBeanDefinition();
this.beanName = beanDefinitionHolder.getBeanName();
this.aliases = beanDefinitionHolder.getAliases();
}
/**
* 返回BeanDefinition.
*/
public BeanDefinition getBeanDefinition() {
return this.beanDefinition;
}
/**
* 返回BeanDefinition的beanName
*/
public String getBeanName() {
return this.beanName;
}
/**
* 返回BeanDefinition的别名
*/
public String[] getAliases() {
return this.aliases;
}
@Override
public Object getSource() {
return this.beanDefinition.getSource();
}
public boolean matchesName(String candidateName) {
return (candidateName != null && (candidateName.equals(this.beanName) ||
candidateName.equals(BeanFactoryUtils.transformedBeanName(this.beanName)) ||
ObjectUtils.containsElement(this.aliases, candidateName)));
}
}
最后调用BeanDefinitionReaderUtils的registerBeanDefinition方法将BeanDefinition注册到bean工厂中。
ClassPathBeanDefinitionScanner
扫描指定包下的所有被spring注解注解过的类(如@Component),并生成对应的BeanDefinition。
在AnnotatedBeanDefinitionReader的scan方法中调用ClassPathBeanDefinitionScanner的scan方法,返回值是扫描这些包注册的bean的总数。
public void scan(String... basePackages) {
this.scanner.scan(basePackages);
}
最终调用ClassPathBeanDefinitionScanner的doScan方法。
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
//保存扫描结果BeanDefinitionHolder是BeanDefinition的持有者
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
//所有包逐个扫描
for (String basePackage : basePackages) {
//获取一个包下的所有BeanDefinition
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
//一个个设置Scope
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
//获取bean的名称,如果不指定beanName默认使用类名且首字母小写
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
//如果这个BeanDefinition实现了AnnotatedBeanDefinition接口,由于我们讨论的是AnnotationConfigApplicationContext,所以这里会是true。
if (candidate instanceof AnnotatedBeanDefinition) {
//处理常用定义注解
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
//这里跟AnnotatedBeanDefinitionReader的registerBean方法一样,生成BeanDefinitionHolder,将BeanDefinition注册到bean工厂
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}