spring中BeanFactory是一个很重要的概念,是IOC容器bean的顶级接口。里面定义了一系列的基本功能
- package org.springframework.beans.factory;
- import org.springframework.beans.BeansException;
- public interface BeanFactory {
- String FACTORY_BEAN_PREFIX = "&";
- Object getBean(String name) throws BeansException;
- <T> T getBean(String name, Class<T> requiredType) throws BeansException;
- <T> T getBean(Class<T> requiredType) throws BeansException;
- Object getBean(String name, Object... args) throws BeansException;
- boolean containsBean(String name);
- boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
- boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
- boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;
- Class<?> getType(String name) throws NoSuchBeanDefinitionException;
- String[] getAliases(String name);
而对于FactoryBean接口,它本身也是一个bean:
- package org.springframework.beans.factory;
- public interface FactoryBean<T> {
- T getObject() throws Exception;
- Class<?> getObjectType();
- boolean isSingleton();
- }
在bean实例化的入口处:AbstractApplicationContext类的refresh()方法中:
- <span style="color:#000000;">@Override
- public void refresh() throws BeansException, IllegalStateException {
- synchronized (this.startupShutdownMonitor) {
- // Prepare this context for refreshing.
- prepareRefresh();
- // Tell the subclass to refresh the internal bean factory.
- ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
- // Prepare the bean factory for use in this context.
- prepareBeanFactory(beanFactory);
- try {
- // Allows post-processing of the bean factory in context subclasses.
- postProcessBeanFactory(beanFactory);
- // Invoke factory processors registered as beans in the context.
- invokeBeanFactoryPostProcessors(beanFactory);
- // Register bean processors that intercept bean creation.
- registerBeanPostProcessors(beanFactory);
- // Initialize message source for this context.
- initMessageSource();
- // Initialize event multicaster for this context.
- initApplicationEventMulticaster();
- // Initialize other special beans in specific context subclasses.
- onRefresh();
- // Check for listener beans and register them.
- registerListeners();
- // Instantiate all remaining (non-lazy-init) singletons.
- finishBeanFactoryInitialization(beanFactory);
- // Last step: publish corresponding event.
- finishRefresh();
- }
- protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
- // Initialize conversion service for this context.
- if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
- beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
- beanFactory.setConversionService(
- beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
- }
- // Register a default embedded value resolver if no bean post-processor
- // (such as a PropertyPlaceholderConfigurer bean) registered any before:
- // at this point, primarily for resolution in annotation attribute values.
- if (!beanFactory.hasEmbeddedValueResolver()) {
- beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
- @Override
- public String resolveStringValue(String strVal) {
- return getEnvironment().resolvePlaceholders(strVal);
- }
- });
- }
- // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
- String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
- for (String weaverAwareName : weaverAwareNames) {
- getBean(weaverAwareName);
- }
- // Stop using the temporary ClassLoader for type matching.
- beanFactory.setTempClassLoader(null);
- // Allow for caching all bean definition metadata, not expecting further changes.
- beanFactory.freezeConfiguration();
- // Instantiate all remaining (non-lazy-init) singletons.
- beanFactory.preInstantiateSingletons</span>();
从preInstantiateSingletons方法进去可以看到它是ConfigurableListableBeanFactory接口的方法,由子类DefaultListableBeanFactory实现了该方法,可以看看具体的代码:
- public void preInstantiateSingletons() throws BeansException {
- if (this.logger.isDebugEnabled()) {
- this.logger.debug("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<String>(this.beanDefinitionNames);
- // Trigger initialization of all non-lazy singleton beans...
- for (String beanName : beanNames) {
- RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
- if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
- if (isFactoryBean(beanName)) {
- final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
- boolean isEagerInit;
- if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
- isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
- @Override
- public Boolean run() {
- return ((SmartFactoryBean<?>) factory).isEagerInit();
- }
- }, getAccessControlContext());
- }
- else {
- isEagerInit = (factory instanceof SmartFactoryBean &&
- ((SmartFactoryBean<?>) factory).isEagerInit());
- }
- if (isEagerInit) {
- getBean(beanName);
- }
- }
- else {
- getBean(beanName);
- }
- }
- 在这段代码的中间可以看到:首先判断!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()非抽象、单例、非懒加载的情况时,如果是FactoryBean,那么final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);是通过一个“&”符号获得IOC中的bean,如果不是FactoryBean则直接通过getBean即可。
- https://www.cnblogs.com/jyyzzjl/p/5459335.html 引入另外一篇博文,对后续有更多的解释!
很多开源项目在集成Spring 时都使用到FactoryBean,比如 MyBatis3 提供 mybatis-spring项目中的 org.mybatis.spring.SqlSessionFactoryBean
:
<bean id="tradeSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="trade" />
<property name="mapperLocations" value="classpath*:mapper/trade/*Mapper.xml" />
<property name="configLocation" value="classpath:mybatis-config.xml" />
<property name="typeAliasesPackage" value="com.bytebeats.mybatis3.domain.trade" />
</bean>
org.mybatis.spring.SqlSessionFactoryBean
如下:
package org.mybatis.spring;
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
private static final Log LOGGER = LogFactory.getLog(SqlSessionFactoryBean.class);
......
}
另外,阿里开源的分布式服务框架 Dubbo 中的Consumer 也使用到了FactoryBean:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
">
<!-- 当前应用信息配置 -->
<dubbo:application name="demo-consumer" />
<!-- 暴露服务协议配置 -->
<dubbo:protocol name="dubbo" port="20813" />
<!-- 暴露服务配置 -->
<dubbo:reference id="demoService" interface="com.alibaba.dubbo.config.spring.api.DemoService" />
</beans>
<dubbo:reference
对应的Bean是com.alibaba.dubbo.config.spring.ReferenceBean
类,如下:
public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean {
}