欢迎光临我的个人博客:https://www.jelliclecat.cn/
前置
Spring阅读前言-里面讲了一些心路历程
spring-beans包源码阅读-2-BeanWrapper
spring-beans包源码阅读-3-BeanDefinition
终于到重点啦!由于BeanFactory太复杂了,这次我们会用单元测试调试跟踪源码。
一. BeanFactory和FactoryBean
先聊一聊BeanFactory和FactoryBean,期初我看源码的时候,看到这两个接口真是异常懵逼,他们的方法还很相似,都是获取一个Object。其实这两个接口八竿子打不着,九杆子能打着一点,这里就先讲一讲这两个接口各是干什么的。
1. BeanFactory
spring的总工厂,所有的bean的实例都保存在这个工厂中,并提供了各种不同的方法去获取各种的bean的实例。这个接口没啥好多说的,最核心的接口,等下我们会重点分析这个接口。
2. FactoryBean
从名字来看,首先这是一个Bean,然后这是一个工厂,其部分注释如下:
* If a bean implements this
* interface, it is used as a factory for an object to expose, not directly as a
* bean instance that will be exposed itself.
*
* NB: A bean that implements this interface cannot be used as a normal bean.
* A FactoryBean is defined in a bean style, but the object exposed for bean
* references ({@link #getObject()}) is always the object that it creates.
public interface FactoryBean {
@Nullable
T getObject() throws Exception;
...
}
FactoryBean才是真正的我们熟悉的"工厂方法模式",其实命名为Factory会更好,但是在spring中,所有的实体都是Bean,一个Factory也不例外是一个Bean,所以就命名为了FactoryBean。实现了这个接口的类就是一个工厂类,里面需要实现获取具体对象的逻辑。
3. FactoryBean,工厂方法模式
这里不会详细介绍什么是工厂模式,因为在进行spring源码阅读的时候会假定已经掌握了各种常用的设计模式。
那么FactoryBean是怎么使用工厂方法模式的呢?
FactoryBean有一个直接实现类:AbstractFactoryBean,里面实现了T getObject() throws Exception
方法:
/**
* Expose the singleton instance or create a new prototype instance.
* @see #createInstance()
* @see #getEarlySingletonInterfaces()
*/
@Override
public final T getObject() throws Exception {
if (isSingleton()) {
return (this.initialized ? this.singletonInstance : getEarlySingletonInstance());
}
else {
return createInstance();
}
}
/**
* Template method that subclasses must override to construct
* the object returned by this factory.
* Invoked on initialization of this FactoryBean in case of
* a singleton; else, on each {@link #getObject()} call.
* @return the object returned by this factory
* @throws Exception if an exception occurred during object creation
* @see #getObject()
*/
protected abstract T createInstance() throws Exception;
最后扔给了一个模板方法createInstance()去完成具体的实例的创建工作,这就是一个标准的工厂模式。
二. How getBean() works.
BeanFactory接口的集大成者就是DefaultListableBeanFactory,整个Bean的实例化过程、实例化策略等等内容,都在DefaultListableBeanFactory以及其父类AbstractAutowireCapableBeanFactory和AbstractBeanFactory中,故也是我们研究的重点对象。
这个继承关系也是没谁了。。
1. AliasRegistry & SimpleAliasRegistry
bean可能有各种别名,这个接口用来提供给一个Bean添加一些别名,并提供根据某个别名查找一个Bean的逻辑。所有的别名引用关系保存在一个map中,取的时候是递归算法:
// SimpleAliasRegistry.java
/**
* Transitively retrieve all aliases for the given name.
* @param name the target name to find aliases for
* @param result the resulting aliases list
*/
private void retrieveAliases(String name, List result) {
this.aliasMap.forEach((alias, registeredName) -> {
if (registeredName.equals(name)) {
result.add(alias);
retrieveAliases(alias, result);
}
});
}
2. DefaultSingletonBeanRegistry
提供了保存单例Bean的Map、Set等集合,不仅仅是完全体的Bean,也有正在创建中的Bean,以及Bean之间的依赖关系都在这里。常说的"spring容器"中的容器,按我的理解就是这个类了。看看这个类的属性,就知道它的功能:
/** Cache of singleton objects: bean name to bean instance. */
private final Map singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
private final Map earlySingletonObjects = new HashMap<>(16);
/** Set of registered singletons, containing the bean names in registration order. */
private final Set registeredSingletons = new LinkedHashSet<>(256);
/** Names of beans that are currently in creation. */
private final Set singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/** Names of beans currently excluded from in creation checks. */
private final Set inCreationCheckExclusions =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/** List of suppressed Exceptions, available for associating related causes. */
@Nullable
private Set suppressedExceptions;
/** Flag that indicates whether we're currently within destroySingletons. */
private boolean singletonsCurrentlyInDestruction = false;
/** Disposable bean instances: bean name to disposable instance. */
private final Map disposableBeans = new LinkedHashMap<>();
/** Map between containing bean names: bean name to Set of bean names that the bean contains. */
private final Map> containedBeanMap = new ConcurrentHashMap<>(16);
/** Map between dependent bean names: bean name to Set of dependent bean names. */
private final Map> dependentBeanMap = new ConcurrentHashMap<>(64);
/** Map between depending bean names: bean name to Set of bean names for the bean's dependencies. */
private final Map> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
3. FactoryBeanRegistrySupport
这个类提供了对FactoryBean的支持,有一些bean不是直接创建的,而是通过FactoryBean工厂创建的,我们在上文讲过了FactoryBean。这个类的主要功能就是从FactoryBean中调用getObject方法拿到工厂创建出来的实例。
/**
* Obtain an object to expose from the given FactoryBean.
* @param factory the FactoryBean instance
* @param beanName the name of the bean
* @return the object obtained from the FactoryBean
* @throws BeanCreationException if FactoryBean object creation failed
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
private Object doGetObjectFromFactoryBean(final FactoryBean> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction
很简单的一个类,不多讲了,这个类的代码也很简单,主要做了各种异常控制、权限检查、log打印,真正的关键代码只有object = factory.getObject();
这一行。
4. AbstractBeanFactory & AbstractAutowireCapableBeanFactory
里面实现了BeanFactory中的核心方法:getBean
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
/**
* Return an instance, which may be shared or independent, of the specified bean.
*/
protected T doGetBean(final String name, @Nullable final Class requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
...
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);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
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);
}
...
}
前面如果设置了ParentBeanFactory,那么调用ParentBeanFactory去getBean。
先根据beanName拿到RootBeanDefinition,然后递归解析bean的所有依赖,朋友们可以想一下这个过程,最后保证当前所有的依赖都已经创建了,然后开始准备创建当前bean。
可以看到创建bean的工作委托给了createBean,这个方法在子类AbstractAutowireCapableBeanFactory中实现:
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
...
// 真正创建bean的类
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
...
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
... // 省略了其他代码
instanceWrapper = createBeanInstance(beanName, mbd, args);
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
...
}
/**
* Initialize the given bean instance, applying factory callbacks
* as well as init methods and bean post processors.
* Called from {@link #createBean} for traditionally defined beans,
* and from {@link #initializeBean} for existing bean instances.
*/
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
这里就非常清晰了:
首先委托给了真正的创建方法:doCreateBean
doCreateBean实例化Bean分三步走:
doCreateBean中首先调用createBeanInstance实例化Bean,这个时候Bean被实例化了。createBeanInstance中根据各种不同的配置,采用不同的构造函数进行实例化。
doCreateBean中然后调用populateBean方法,改方法将Bean的各种依赖通过BeanWrapper提供的对属性的编辑方法,设置到Bean中。这一步完成了Bean的依赖的组装。
doCreateBean最后调用了initializeBean,意为初始化Bean,这个时候的Bean已经是一个Object实例,并且Bean中通过@Autowire设置的依赖也全部设置完毕。但是最后还有一些初始化工作要做,看代码:首先,如何这个Bean实现了各种Aware接口,则依次调用这些接口的set方法设置信息;然后调用所有的BeanPostProcessors中的Before方法;然后调用通过"init-method"指定的init方法;最后调用所有BeanPostProcessors中的After方法。
最后,这些方法一层一层向上返回了初始化完成的Bean实例。
返回到AbstractBeanFactory中后调用了getObjectForBeanInstance(),检查返回的Bean Instance是否是FactoryBean,如果是,则调用getObject方法获取真正的实例。
创建完后的Bean会放进各种Map中,前面已经讲过了,下次再次getBean的时候,就是从缓存中获取了。
三. 总结
我们没有讲Spring是怎么扫描并将各种标注了@Service的Class转换成BeanDefinition的,上面的过程是在所有的BeanDefinition已经生成并存储在内存中之后执行的。BeanFactory有一个实现类叫做XmlBeanFactory,虽然已经被遗弃了,但是里面展示了如何将application.xml中定义的Bean转化成BeanDefinition的过程,这些都不是这篇文章的重点。这篇文章重点讲解了BeanFactory的每一级继承结构,以及调用getBean的时候发生了什么,Bean的实例是如何被创建并返回的,Aware接口是什么时候被调用的。
在代码中我们可以清晰的看到一个bean被初始化的生命周期:实例化->组装各种依赖->调用Aware接口方法->调用BeanPostProcessor的before方法->指定的"init-method"方法->调用BeanPostProcessor的after方法。关于生命周期,《Spring In Action》这本书中有详细讲解。
其实到这里spring-beans模块的核心部分就已经讲完了,里面还有一些接口如:Aware、InitializingBean、DisposableBean、BeanReference等,这些都是常用接口,但是这些接口没啥好讲的,都是基于实践意义上的接口。关于RootBeanDefinition和ChildBeanDefinition是如何合并的这里也没有多说,比较简单,基于java的继承和多态机制仿的一个工能,所以也不说了。
之后可能会讲一讲spring-context包和spring-mvc包中的一些常用接口,但是我认为spring的灵魂部分,到这里算是讲完了。
其实究其本质呢,bean的初始化底层依赖两个工具,那就是反射和自省,用反射实例化Bean以及调用一些方法(如init-method),用自省去设置Bean的各种属性。中间做的各种工作,都是对这两个底层调用的封装,BeanWrapper就是对自省功能的封装,BeanDefinition是对Bean的设置,BeanFactory是对反射功能的封装。
除了spring的主体功能之外,还有异常的封装、log的打印等都是值得好好研究和学习的地方,以后有时间我也会给朋友们写一写。
如果文章中有任何不对的地方,请您不吝赐教,也欢迎加我微信交流~
欢迎光临我的个人博客:https://www.jelliclecat.cn/