文章目录
为什么要看Spring源码
- 解决使用框架时遇到的问题
- 深入理解底层原理,帮助更好的使用框架
- 深入理解面向对象思想和深入理解设计模式
- 高级程序员的常见面试点
如何看源码
- 确定主线,即想看那个流程的源码
- 找到流程入口
- 参考相关文档
- 寻找源代码规律
Spring中的IoC容器
在Spring中,有两种主要的容器类型,一种是BeanFactory,一种是ApplicationContext。其中BeanFactory是底层的容器实现,提供了IoC容器的基础功能,而ApplicationContext是一种应用级的容器,除了基础功能外还提供了更加丰富的功能,例如:
- 支持不同的信息源
- 支持事件发布
- 在ApplicationContext中提供附加服务
BeanFactory
BeanFactory是Spring中对IoC容器的核心抽象,在BeanFactory中定义了IoC容器的核心方法
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
从接口中的方法签名可以很清楚的看到,BeanFactory提供了作为容器的基本功能。
基于BeanFactory,Spring提供了一系列的子接口即实现类来丰富BeanFactory,使其成为一个强大的IoC容器。BeanFactory的主体结构如下图所示:
Spring源码乍看给人一种很复杂的感觉,但如果把主体结构抽取出来,就可以很清楚的看到它的轮廓。
从图中可以看出,接口层主要包含了四个层次,从上到下依次是一个不断丰富功能的过程。
首先是BeanFactory,这是Spring IoC容器的顶级接口,上面已经介绍过。
往下走,分别是三个平级的接口,分别是ListableBeanFactory/AutowireCapableBeanFactory/HierachialBeanFactory,这三个接口都对BeanFactory进行了扩展。从名称可以比较明显的看出这几个接口扩展的方面。
ListableBeanFactory
boolean containsBeanDefinition(String beanName);
int getBeanDefinitionCount();
String[] getBeanDefinitionNames();
String[] getBeanNamesForType(ResolvableType type);
String[] getBeanNamesForType(Class<?> type);
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;
String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
throws NoSuchBeanDefinitionException;
从接口签名中可以看出,ListablebeanFactory提供了Bean枚举相关的功能,如获取所有bean的名称及bean的总数量,获取bean名称和bean的映射等。
第二个接口是AutowireCapableBeanFactory,这个接口在BeanFactory的基础上扩展了自动装配的功能,例如创建Bean/自动配置bean/解析依赖以及与bean生命周期相关的功能。
代码略。
第三个接口是HieracicalBeanFactory,这个接口同样扩展子BeanFactory,它提供了在容器存在父子关系场景下与容器继承相关的操作。例如WebApplicationContext及ApplicationContext。
代码略。
至此,第二层继承接口就完事了。下面就是ConfigurablebeanFactory这个接口,这个接口继承自HieracicalBeanFactory,同时又扩展了SingletonBeanFactory,也就是与单例模式的Bean注册相关的功能,之所以这么做,个人理解单例模式是bean最常见的形式,将其注册能力加到稍顶级的接口中,有利于规范下层实现的行为。
代码略。
ConfigurableListableBeanFactory是第三层接口,这个接口同时继承了ListableBeanFactory
,AutowrieCapablebeanFactory
和ConfigurableBeanFactory
这三个接口,可以把它理解为spring中常用容器的顶级接口,它定义了一个功能完善的IoC容器的几乎所有行为。
代码略。
至此,BeanFactory体系的主体框架就看完了。
BeanDefinition
BeanDefinition是spring中对bean及bean依赖关系的抽象,如果把spring比做一个制造并管理bean的工厂的话,那BeanDefinition就是创造bean的原材料。
在spring启动过程中,spring会解析配置文件或配置类,将对应的bean定义解析成BeanDefinition并注册到spring容器中,在后续,spring会根据这些具体的BeanDefinition对象来创建并初始化这些bean。
BeanDefinition的继承结构如下:
Spring容器的初始化流程
由于我们在日常开发中经常使用的IoC容器是ApplicationContext,而不是更加底层的BeanFactory,所以在分析Spring容器初始化时,就以ApplicationContext为例,下面是ApplicationContext的体系结构
IoC容器的使用
由于在日常开发中,最常见的是ClassPathXmlApplicationContext,所以就以此为例来分析。首先看一下在日常开发中基本的使用方式。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
ApplicationContext ctx = new ClasspPthXmlApplicationContext("spring.xml");
容器初始化入口
ClassPathXmlApplicationContext.java
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
AbstractApplicationContext.java
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//Step1: 刷新预处理
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//Step2:创建IoC容器,解析xml,注册BeanDefinition
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//Step3:对IoC容器进行预处理
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//Step4:
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//Step5:调用BeanFactoryPostProcessor后置处理器对BeanDefinition进行处理
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//Step6:注册BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
//Step7:初始化消息源(国际化)
initMessageSource();
// Initialize event multicaster for this context.
//Step8:初始化应用事件广播
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
//Step9:初始化一些特殊的bean
onRefresh();
// Check for listener beans and register them.
//Step10:注册监听器
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//Step11:实例话单例Bean,Bean的依赖注入和AOP都发生在这一步
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//Step12:完成,发布事件
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容器初始化的核心流程:
- 创建容器
- 加载配置资源文件
- 解析并注册BeanDefinition
- 完成bean的创建与初始化
这四个步骤对应到上面的refresh方法中,其中前三步是在step2中完成,第四步主要是在step11中完成。
解析&注册BeanDefinition
1.AbstractApplicationContext.java
/**
a)创建IoC容器
b)加载xml文件
c)解析并生成BeanDefinition,并注册到容器中
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
2.AbstractApplicationContext.java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
/**
a)销毁存在的容器
b)创建BeanFactory
c)加载资源文件,并向容器中注册BeanDefinition
*/
refreshBeanFactory();
/**
返回上一步创建的BeanFactory
*/
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
3.AbstractRefreshableApplicationContext.java
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
/**
创建BeanFactory,这一步直接通过new创建来一个DefaultListableBeanFactory
new DefaultListableBeanFactory(getInternalParentBeanFactory());
*/
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
/**
加载BeanDefinition
*/
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
4.AbstractXmlApplicationContext.java
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
/**
初始化BeanDefinitionReader来完成文件都读取和
加载BeanDefinition。
*/
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
initBeanDefinitionReader(beanDefinitionReader);
/**
加载BeanDefinition,由子类完成。
protected Resource[] getConfigResources() {
return null;
}
*/
loadBeanDefinitions(beanDefinitionReader);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
/**
由子类完成:ClassPathXmlApplicationContext
protected Resource[] getConfigResources() ;
*/
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
5.ClassPathXmlApplicationContext.java
//初始化Resource是在创建具体的ClassPathXmlApplicationContext时进行的。
public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, ApplicationContext parent)
throws BeansException {
super(parent);
Assert.notNull(paths, "Path array must not be null");
Assert.notNull(clazz, "Class argument must not be null");
this.configResources = new Resource[paths.length];
for (int i = 0; i < paths.length; i++) {
this.configResources[i] = new ClassPathResource(paths[i], clazz);
}
refresh();
}
@Override
protected Resource[] getConfigResources() {
return this.configResources;
}
6.AbstractBeanDefinitionReader.java
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
/**
此处时核心调用逻辑,最终会进入到具体实现类
XmlBeanDefinitionReader中进行处理
*/
int loadCount = loadBeanDefinitions(resources);
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}
7.XmlBeanDefinitionReader.java
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
try {
/**
此处调用的getResource是由具体的ApplicationContext
提供的。
*/
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
/**
最终执行加载xml/解析BeanDefinition并进行注册的
核心方法。
*/
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
}
8.XmlBeanDefinitionReader.java
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource){
/**
BeanDefinitionReader这个组件的主要作用就是将xml解析成
Document对象,然后它就会将任务转交给BeanDefinitionDocumentReader
*/
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
9.上接getResource
getResoruce()方法的作用是加载配置信息对应的Resource流对象,这个方法被定义在ResourceLoader接口中
public interface ResourceLoader {
String CLASSPATH_URL_PREFIX = "classpath:";
Resource getResource(String var1);
ClassLoader getClassLoader();
}
而ApplicationContext的顶级父类AbstractApplicationContext继承了DefaultResourceLoader(),子类ApplicationContext可以同覆盖getResource()来实现自己的加载配置信息的方式。
10.XmlBeanDocumentReader.java
BeanDefinitionReader会将解析&注册任务交给BeanDefinitionDocumentReader来完成
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 创建DocumentReader
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
// 将任务转交给DocumentReader
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
11.DefaultBeanDefinitionDocumentReader.java
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
//解析默认名称空间
delegate.parseCustomElement(ele);
}
}
}
}
else {
//解析其他名称空间
delegate.parseCustomElement(root);
}
}
这里涉及到一个重要的操作,就是确定NamespaceHandler,在parseCustomElement方法中主要来处理
import/bean/beans等spring的核心标签,在parseCustomElement方法中主要来处理aop/context/mvc
等其他名称空间中的标签。
在处理其他名称空间的标签时,需要首先找到对应的NamespaceHandler,这个过程是通过加载classpath
下的spring.handler文件完成的,在spring.hander文件中定义了每一种名称空间对应的NameSpaceHandler
12.BeanDefinitionParserDelegate.java
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
/**
这一步就是从spring.handler中寻找对应的NamespaceHandler
*/
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
BeanDefinitionReader继承结构
BeanDefinitionReader的主要作用是读取外部资源文件,解析成BeanDefintion
BeanDefinitionReader
AbstractBeanDefinitionReader
GroovyBeanDefinitionReader
XmlBeanDefinitionReader
PropertiesBeanDefinitionReader
总结一下
- spring容器的启动入口是refresh()方法,在refresh()方法中定义了spring IoC容器初始化的骨架,为Bean的生命周期管理提供了条件;
- 默认的IoC Bean工厂是DefaultListableBeanFactory;
- BeanDefinition是spring中对Bean对象及其依赖关系的抽象;
- ApplicationContext通过实现ResourceLoader接口实现加载Bean定义信息的具体方式;
- BeanDefinitionReader负责从Resource中解析BeanDefinition,并将BeanDefintion注册到IoC 容器中;
- BeanDefinitionReader注册BeanDefinition是通过BeanFactory实现的BeanDefinitionRegistry接口提供的相关能力实现的;
- ApplicationContext是一个持有BeanFactory的/功能被强化了的IoC容器
- 最终被解析出来的BeanDefinition被注册到了BeanFactory的HashMap中;
- BeanDefinitionReader的主要任务是将xml解析成Document,然后它就会将具体的解析和注册BeanDefinition的任务交给BeanDefinitionDocumentReader;
- 对于不同的名称空间中的标签,是通过在spring.handler中定义其对应关系来指定对应的NamespaceHandler的;
Bean的实例化&依赖注入
bean实力化
在IoC容器顶级接口BeanFactory中声明了getBean()的一些列重载方法,Bean的实例化和依赖注入都是从这里开始是(lazy-init=false除外),下面我们从AbstractBeanFactory中都getBean开始入手,来看一下Spring bean的实例化过程。
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
//这里定义了bean初始化和依赖入住的最顶层逻辑
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//尝试从缓存中获取单例bean,这里包含了解决循环依赖的核心逻辑,后面再单独进行分析
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//此处,处理FactoryBean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
//此处处理具有继承关系的容器体系,利用递归顺着BeanFactory继承链向上找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
getBean(dep);
}
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
/**
此处进入创建bean的核心逻辑
*/
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//处理 prototype bean
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
// 更新bean 的创建状态
beforePrototypeCreation(beanName);
try {
//进入创建bean的核心逻辑
return createBean(beanName, mbd, args);
}
finally {
// 更新创建bean的状态
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
从上面的代码中我们可以看出,doGetBean中会继续调用createBean()
方法来完成bean的创建,那么我们就来分析一下createBean()
这个方法
AbstractBeanFactory.java:
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
throws BeanCreationException;
AbstractAutowireCapableBeanFactory.java
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//此处处理实现来BeanPostProcessor 的Bean,会返回一个代理对象
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
/**
下面进入正在创建bean对象的doCreateBean()方法中
*/
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
/**
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//step1: 创建实例对象
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//step2: 填充属性
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// step3:调用init方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
小结
从上面三个方法中可以清楚的看出创建bean的主体过程
- 判断bean 类型(bean or factorybean)和scope类型
- 为实现来BeanPostProcessor的bean创建代理对象
- 利用构造函数/反射创建bean对象(createBeanInstance)
- 填充属性(populateBean)
- 调用init初始化方法
循环依赖问题
在进行依赖注入是, 如果bean A依赖于bean B,那么在初始化A的时候,会先去初始化B。那么,如果A依赖于B,同时B由依赖于A怎么办呢?
依赖的类型有两种,一种是构造启依赖,一种的属性setter依赖,那么就可以把循环依赖分为以下几种:
- A的构造方法中依赖了B的实例对象,同时B的构造方法中依赖了A的实例对象
- A的构造方法中依赖了B的实例对象,同时B的某个field或者setter需要A的实例对象,以及反之
- A的某个field或者setter依赖了B的实例对象,同时B的某个field或者setter依赖了A的实例对象,以及反之
对于第1种情况,是没办法解决的,因为没办法把创建对象和设置属性值用一步完成。
Spring是通过三个级别的缓存来解决循环依赖问题的,解决思路简单的说就是将创建对象和设置属性分开进行。
这三个缓存分别是:
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
下面再看一下下面的代码段:
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
首先解释一下上面说的三个缓存:
singletonObjects:存放创建好的单例对象
singletonFactories:存放用于创建某个单例bean的工厂对象,该工厂从earlySingletonObjects中得到对象
earlySingletonObjects:存放被提前曝光的单例bean对象
下面以一个例子来说明处理流程:
a依赖于b,b依赖于a,前提是setter依赖,处理过程大致如下:
- getBean(b);
- 利用b的构造函数创建b对象,并将其放入earlySingletonObjects中,发现其依赖于a,则更新b状态为正在创建
- 转而去利用a创建a的实例对象,发现a对象依赖于b
- 首先,查找singletonObjects,若没有,查找singletonFactories,找到对应的Factory
- 该factory会从earlySingletonObjects中找到被提前曝光的a
- 虽然此时a并不完整,因为b属性还没注入,单此时,b对象可以注入a
- 此时b创建完成,b被放入singletonObjects中
- 创建a的步骤继续往下走,尝试从singletonObjects中获取b
- 因为b已经创建完成,所以获取b对象成功,然后继续注入a的b属性
- a创建完成,a被放入singletonObjects中
- 循环依赖bean创建结束
Spring AOP原理
分析aop原理要从下面三个方面入手:
- 如果根据标签查找对应的BeanDefinitionParser
- BeanDefinitionParser的解析流程
- 产生apo代理的流程(何时/如何产生代理)
查找BeanDefinitionReader
回顾BeanDefinition的解析过程:
BeanDefinitionReader->BeanDefinitionDocumentReader(DefaultBeanDefinitionDocumentReader)->BeanDefinitionParserDelegate->.parseCustomElement()
//在该方法中通过具体的NameSpaceHandler来解析xml
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
查找NamespaceHandler是通过查找classpath下的spring.handler来实现的,在spring.handler中定义了名称空间和具体的NamespaceHandler之间的关系
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
AopNamespaceHandler
public interface NamespaceHandler {
void init();
BeanDefinition parse(Element element, ParserContext parserContext);
BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext);
}
public class AopNamespaceHandler extends NamespaceHandlerSupport {
public AopNamespaceHandler() {
}
public void init() {
this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
以上就是AopNamespaceHandler的全貌,可以清楚的看到最常用的两个标签对应的前缀
<aop:aspectj-autoproxy>
<aop:config>
<aop:pointcut id="" expression=""></aop:pointcut>
<aop:aspect ref="">
<aop:before method="" pointcut-ref=""/>
</aop:aspect>
</aop:config>
而解析动作是在BeanDefinitionParserDelegate的parseCustomElement()方法中开始的
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
//次数就是调用NamespaceHandler中的parse方法
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
紧接着,就进入到AopNamespaceHandler中到parse()方法中,最终通过具体的BeanDefinitionParser来解析xml标签,先来看一下ConfigBeanDefinitionParser
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
//创建一个用于创建代理对象的ProxyFactory
this.configureAutoProxyCreator(parserContext, element);
List<Element> childElts = DomUtils.getChildElements(element);
Iterator var5 = childElts.iterator();
while(var5.hasNext()) {
Element elt = (Element)var5.next();
String localName = parserContext.getDelegate().getLocalName(elt);
//解析<aop:pointcut/>
if ("pointcut".equals(localName)) {
this.parsePointcut(elt, parserContext);
//解析<aop:advisor/>
} else if ("advisor".equals(localName)) {
this.parseAdvisor(elt, parserContext);
//解析<aop:aspect/>
} else if ("aspect".equals(localName)) {
this.parseAspect(elt, parserContext);
}
}
parserContext.popAndRegisterContainingComponent();
return null;
}
切入点 + 切面 + 目标类 + ProxyFactory = 代理对象
Advice
解析每个标签是会产生一个BeanDefinition,pointcut对应的是AspectJExpressionPointcut
,advicer对应的是DefaultBeanFactoryPointcutAdvisor
,aspect对应的是AspectComponentDefinition
,advice对应的是AspectJMethodBeforeAdvice/AspectJAfterAdvice/AspectJAfterReturningAdvice/AspectJAfterThrowingAdvice/AspectJAroundAdvice
,解析标签的过程就是创建这些类对应的对象的过程,然后会将对应的BeanDefinition注册到Spring容器中。
所有类都实现类Advice接口,这是AOP联盟都规定。
AOP核心原理
从上面都源码中可以看到,AopNamespaceHandler中都parse方法主要做了两件事情:
- 向容器中注册AspectJAwareAdvisorAutoProxyCreator
- 解析xml,生成BeanDefinition并注册到spring容器中
其中,AspectJAwareAdvisorAutoProxyCreator的主要作用是在初始化bean的时候被调用,根据parse()方法解析出来的BeanDefinition来创建代理对象。
下面看一下生成代理类的核心逻辑。
由于Spring的在第一次获取bean的时候创建对象的(lazy-init=false除外),所以入口就是AbstractBeanFactory的getBean(Class<?> type)方法,最终调用链进入到AbstractAutowiredCapableBeanFactory
的doCreateBean()
方法中
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
/**
此处就会处理所有实现类BeanPostProcessor接口的Bean,
由于AspectJAwareAdvisorAutoProxyCreator实现了
BeanPostProcessor接口,所以此处就会调用postProcessAfterInitialization方法
*/
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
/**
AbstractAutoProxyCreator的postProcessAfterInitialization()方法
是创建代理对象的核心入口
*/
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
接下来就进入到wrapIfNessary(bean,beanName,cachekey)方法中
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
/**
根据Bean获取与其关联的所有Advisor
*/
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//生成代理对象
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
经过层层调用,最终进入到了DefaultAopProxyFactory的createAopProxy()方法中
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
} else {
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
代码已经看的非常清晰了,spring提供了两种代理实现:JDK动态代理和Cglib字节码代理。
总结
总结一下aop的核心实现思路:
- referer()方法被调用时,通过spring.handler定义到具体的NamespaceHandler,并调用init方法注册具体的Parser,然后有Parser解析不同类型的标签
- 解析时,将pointcut/advisor/aspect分别解析成对应的PointCut和Advice类,并注册到Spring容器中
- 调用BeanFactory的getBean()时,触发bean的初始化
- 由于解析时,向容器中注册了一个用于创建代理对象的ProxyCreator,并且这个Creator实现了BeanPostProcessor,所以,由于在初始化时,spring会统一处理BeanPostProcessor,所以ProxyCreator的after方法被调用
- 在ProxyCreator的after方法中获取当前bean对应的advice
- 然后调用ProxyFactory(DefaultAopProxyFactory)的createProxy()方法
- createProxy()方法根据是否实现了接口来选择采用JDK动态代理或Cglib静态代理来生成代理对象
- 最终用户调用到的对象就是被织入来切面的代理对象