Spring Bean
的创建刚开始进行了一些准备工作,比如转换服务的初始化,占位符解析器的初始化, BeanDefinition
元数据的冻结等操作,都是为了在创建Bean的过程中保证 Bean
的正确的创建,接下来开始进行对 Bean
的创建进行解析。
Bean 的创建步骤
在 Spring
源码中对 Bean
的创建遵循一个步骤就是: getBean
--> doGetBean
--> createBean
--> doCreateBean
,常规的 Bean
的创建过程都是按照这个步骤执行,然后反射实例化,属性填充,初始化,放到一级缓存中。那么非常规的有可能就不遵循这个步骤,比如 FactoryBean
, InstantiationAwareBeanPostProcessor
等。
上源码:
public void preInstantiateSingletons() throws BeansException { if (logger.isTraceEnabled()) { logger.trace("Pre-instantiating singletons in " + this); } // Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... // 遍历所有的beanName for (String beanName : beanNames) { // 获取RootBeanDefinition 从缓存中,第一个放入缓存是在 AbstractApplicationContext#invokeBeanFactoryPostProcessors 中的getBeanNamesForType方法中 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); // 如果不是抽象的,是单例的,是非懒加载的,则进行bean的创建,否则直接跳过 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { // 是否是FactoryBean if (isFactoryBean(beanName)) { // 获取bean实例 Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); // 判断获取的Bean是否是FactoryBean if (bean instanceof FactoryBean) { FactoryBean<?> factory = (FactoryBean<?>) bean; // 是否是饥饿初始化,默认是false boolean isEagerInit; // 权限校验 if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged( (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } // 如果是饥饿初始化,则进行bean的创建 if (isEagerInit) { getBean(beanName); } } } else { // 获取bean getBean(beanName); } } } // Trigger post-initialization callback for all applicable beans... // 触发 所有Bean初始化后的回调 for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); // 获取单例对象,如果是SmartInitializingSingleton 则调用afterSingletonsInstantiated // 在监听器中使用@EventListener注解标记的方法就是在这个方法中进行监听器的添加的,会创建一个监听器的适配器 // 调用类为 EventListenerMethodProcessor if (singletonInstance instanceof SmartInitializingSingleton) { SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; // 权限检查 if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } }
通过源码可以知道, Spring
前期在进行 XML
进行 loadBeanDefinitions
加载或者 BeanFactoryPostProcessor
子类 BeanDefinitionRegistryPostProcessor
的实现类 ConfigurationClassPostProcessor
注解解析 出来的 BeanDefinition
放入两个集合 BeanDefinitionMap
和 BeanDefinitionNames
,这里遍历的是 BeanDefinitionNames
这个集合,存放的是 beanName
。
首先是进行了BeanDefinition的合并处理,最终返回的全是RootBeanDefinition,进入源码可以看到这里是从缓存中获取的,如果有则直接取出来,否则再去解析。
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException { // Quick check on the concurrent map first, with minimal locking. // 从缓存中获取 RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName); if (mbd != null && !mbd.stale) { return mbd; } return getMergedBeanDefinition(beanName, getBeanDefinition(beanName)); }
那么第一次进行调用时什么地方呢?是在进行 BeanFactoryPostProcessor
的执行和解析时调用的,在解析 BeanFactoryPostProcessor
时调用了 getBeanNamesForType
方法,然后调用 doGetBeanNamesForType
时进行了 BeanDefinitionNames
集合的遍历合并 Bean
:
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) { List<String> result = new ArrayList<>(); // Check all bean definitions. // 遍历所有的BeanDefinitionNames集合 for (String beanName : this.beanDefinitionNames) { // Only consider bean as eligible if the bean name is not defined as alias for some other bean. if (!isAlias(beanName)) { try { // 从本地缓存中获取合并的BeanDefinition RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // Only check bean definition if it is complete. if (!mbd.isAbstract() && (allowEagerInit || (mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) && !requiresEagerInitForType(mbd.getFactoryBeanName()))) { // 是否是FactoryBean boolean isFactoryBean = isFactoryBean(beanName, mbd); BeanDefinitionHolder dbd = mbd.getDecoratedDefinition(); boolean matchFound = false; boolean allowFactoryBeanInit = (allowEagerInit || containsSingleton(beanName)); boolean isNonLazyDecorat // 省略代码.... } } } }
所以在执行 preInstantiateSingletons
预实例化单例时获取的 RootBeanDefinition
基本是从缓存中获取的。
接着是判断如果是单例的并且不是抽象的,不是懒加载的,那么就进行 Bean
的创建,然后又判断是否是 FactoryBean
,如果是那么就进行下一步逻辑。
FactoryBean 是什么?
FactoryBean
是用来创建 Bean
对象的,他是一个接口,方法:
getObject
获取bean对象getObjectType
获取bean的类型isSingleton
是否是单例的,默认是true
在创建对象时,你可以直接在 getObject
方法中进行 new
,或者反射,或者是其他都可以,非常的灵活。接下来使用 FactoryBean
进行自定义的 Bean
的创建。
定义一个 FactoryBean
的实现类:
/** * @author <a href="https://www.cnblogs.com/redwinter/">redwinter</a> * @since 1.0 **/ public class MyFactoryBean implements FactoryBean<MyUser> { @Override public MyUser getObject() throws Exception { // 直接new一个对象 return new MyUser(); } @Override public Class<?> getObjectType() { return MyUser.class; } @Override public boolean isSingleton() { return true; } }
定义 MyUser
/** * @author <a href="https://www.cnblogs.com/redwinter/">redwinter</a> * @since 1.0 **/ public class MyUser { }
xml配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <bean id="myFactoryBean" class="com.redwinter.selffactorybean.MyFactoryBean"/> </beans>
测试类:
/** * @author <a href="https://www.cnblogs.com/redwinter/">redwinter</a> * @since 1.0 **/ public class FactoryBeanTest { @Test public void test(){ MyClassPathXmlApplicationContext context = new MyClassPathXmlApplicationContext("spring-factory.xml"); Object myFactoryBean = context.getBean("myFactoryBean"); System.out.println(myFactoryBean); Object myFactoryBean2 = context.getBean("&myFactoryBean"); System.out.println(myFactoryBean2); } }
输出:
com.redwinter.test.selffactorybean.MyUser@2d554825 com.redwinter.test.selffactorybean.MyFactoryBean@68837a77
这里可以看到 FactoryBean
创建 Bean
的时候, xml
注册的是一个 FactoryBean
的实现,但是获取出来又是具体的 MyUser
对象,这里 Spring
使用了懒加载的机制,在 Spring
对 Bean
进行初始化时,实际上只将 FactoryBean
的实现类注册到了 Spring
容器中,当我们需要使用的时候,才去判断,如果是 FactoryBean
类型的,那么就去调用 getObject
方法去创建对象。如果是第二次去获取 Bean
,那么是从缓存中获取的,如果是获取 &
前缀的 Bean
,那就直接返回。
protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { // Don't let calling code try to dereference the factory if the bean isn't a factory. // 判断是否是&前缀标识 if (BeanFactoryUtils.isFactoryDereference(name)) { if (beanInstance instanceof NullBean) { return beanInstance; } if (!(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass()); } if (mbd != null) { mbd.isFactoryBean = true; } return beanInstance; } // Now we have the bean instance, which may be a normal bean or a FactoryBean. // If it's a FactoryBean, we use it to create a bean instance, unless the // caller actually wants a reference to the factory. if (!(beanInstance instanceof FactoryBean)) { return beanInstance; } Object object = null; if (mbd != null) { mbd.isFactoryBean = true; } else { // 从缓存中获取 object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // Return bean instance from factory. FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // Caches object obtained from FactoryBean if it is a singleton. if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } // 判断是否是合成的Bean,是否是应用程序本身设置的,比如某些aop 就是合成的Bean boolean synthetic = (mbd != null && mbd.isSynthetic()); // 执行getObject方法获取Bean object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
BeanFactory 和FactoryBean 的区别?
根据前面的文章介绍,我们知道 BeanFactory
是一个 Bean
的创建工厂,比如 AbstractApplicationContext
就是 BeanFactory
的实现类,这个类就是用来创建 Bean
的,创建出来的 Bean
放在缓存中。而 FactoryBean
就是 Bean
实例,是由 BeanFactory
创建的,并且 FactoryBean
也是用来创建 Bean
对象,使用 getObject
方法进行创建,也是会放在缓存中供下次直接获取,而且如果在使用时需要使用 FactoryBean
的实例时需要以 &
前缀才能获取到,比如 getBean("&myFactoryBean");
如果是获取通过 getObject
方法创建的对象时,就不需要添加 &
前缀,比如 getBean("myFactoryBean");
总结一下:
相同点:
- 都是用来创建对象的
- 都是创建出来之后放入缓存中供下次直接使用
不同点:
BeanFactory
是一个对象创建工厂,而FactoryBean
是一个Bean
实例BeanFactory
创建的对象一般来说都是使用反射调用构造函数创建的,而FactoryBean
创建对象是调用getObject
方法创建,并且创建方式不一定是通过反射,可以是直接new
对象或者其他方式FactoryBean
在获取对象时,可以获取到两个对象,一个是存放在BeanFactory
创建的缓存中,通过&beanName
获取的FactoryBean
的实现类对象,一个是调用getObject
创建的,通过beanName
获取的具体对象。
Bean
的创建过程非常复杂,下一篇继续。