两者之间有什么关系,按我的理解,两者并没有什么必然的联系。FactoryBean也是一种Bean,也是通过BeanFactory容器获取。
BeanFactory:The root interface for accessing a Spring bean container.This is the basic client view of a bean container.什么意思?访问bean 容器的根接口,触摸到bean容器的基本客户端。很多接口和类都实现或者继承该接口,比如常用的ApplicationContext、FileSystemXmlApplicationContext、ClassPathXmlApplicationContext、AnnotationConfigApplicationContext等等。这个接口提供了我们对容器的实例化对象的获取。请看代码:
一般我们不用原始接口BeanFactory,功能较少。我们可以使用ApplicationContext接口,它封装了国际化等相关的信息,比较全面。
ApplicationContext context = new AnnotationConfigApplicationContext(AopProxyConfig.class);
AopCity city = (AopCity) context.getBean("aopCity");
FactoryBean
FactoryBean接口由BeanFactory中使用的对象实现,这些对象本身是各个对象的工厂。如果一个bean实现了这个接口,那么它将被用作要公开的对象的工厂,而不是直接用作将自己公开的bean实例。简单点就是,通过FactoryBean对原始Bean做了一层封装,通过context .getBean(“dbFactoryBean”)获取的对象已经被我处理了。直接上代码:
自定义FactoryBean
public class DbFactoryBean implements FactoryBean<FactoryBeanUser> {
private static final Logger logger = LoggerFactory.getLogger(DbFactoryBean.class);
@Override
public FactoryBeanUser getObject() throws Exception {
logger.debug("DbFactoryBean执行...");
FactoryBeanUser user = new FactoryBeanUser();
user.setUserName("张三");
return user;
}
@Override
public Class<?> getObjectType() {
return null;
}
public void printObject(){
logger.debug("DbFactoryBean is {}",this);
}
}
配置类
@Configuration
public class FactoryBeanConfig {
//FactoryBean
@Bean
public DbFactoryBean dbFactoryBean(){
return new DbFactoryBean();
}
//原始对象
@Bean
public FactoryBeanUser factoryBeanUser(){
return new FactoryBeanUser();
}
}
测试类
@Test
public void testFactoryBean(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(FactoryBeanConfig.class);
//通过获取FactoryBean对象我们获取到的是FactoryBeanUser实例
FactoryBeanUser factoryBeanUser = (FactoryBeanUser) context.getBean("dbFactoryBean");
logger.debug("test user name is {}",factoryBeanUser.getUserName());
//如果想要获取DbFactoryBean 我们可以通过增加“&”标识符获取
DbFactoryBean dbFactoryBean = (DbFactoryBean) context.getBean("&dbFactoryBean");
dbFactoryBean.printObject();
//这个就是获取原始FactoryBeanUser对象,没有经过FactoryBean处理
FactoryBeanUser factoryBeanUser1 = (FactoryBeanUser)context.getBean("factoryBeanUser");
logger.debug("test user name is {}",factoryBeanUser1.getUserName());
}
结果:
09:40:14.187 [main] DEBUG org.my.study.factorybean.DbFactoryBean - DbFactoryBean执行...
09:40:14.190 [main] DEBUG org.my.study.aop.ConfigTest - test user name is 张三
09:40:14.195 [main] DEBUG org.my.study.factorybean.DbFactoryBean - DbFactoryBean is org.my.study.factorybean.DbFactoryBean@33617539
09:40:14.195 [main] DEBUG org.my.study.aop.ConfigTest - test user name is null
通过结果我们可以看出FactoryBean的作用,他可以改变一些Bean,实现Bean初始化相关的一些操作。
BeanFactory
首先看看BeanFactory的源码,其实是没啥看的,很多类实现BeanFactory接口。直接看AnnotationConfigApplicationContext,怎么实例化一个Bean工厂的。首先根据我们上边说的测试类里的代码进入AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
紧接着进入this()方法
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
我们知道调用构造方法肯定会先初始化父类构造方法,所以会调用父类GenericApplicationContext的构造方法,我们可以看初始化了一个DefaultListableBeanFactory对象,我们的Bean工厂也就初始化成功了。
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
我们可以看到通过getBean方法我们就可以获取到beanFactory 里的实例。访问bean 容器的根接口,也就是我们可以通过实现类去容器里取我们想要的实例对象。
FactoryBean
我们再看看FactoryBean源码,他其实就是一个Bean,我们看下是怎么通过实现FactoryBean接口就可以获取到包装之后的Bean的。首先我们还是进入这块代码
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
然后紧接着进入refresh()代码里,然后进入finishBeanFactoryInitialization(beanFactory)方法进入下面这个
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
我们看下这个方法里的源码
@Override
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...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//判断是否是FactoryBean
if (isFactoryBean(beanName)) {
//FACTORY_BEAN_PREFIX 值是 “&”
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
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());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
//省略部分源码
}
然后进入getBean()创建实例化Bean。
当通过FactoryBeanUser factoryBeanUser = (FactoryBeanUser) context.getBean(“dbFactoryBean”);获取对象时我们进入getBean()源码里去看最终会进入AbstractBeanFactory类doGetBean方法
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//从缓存里获取实例化DbFactoryBean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//最终进入此方法我们可以看到传入name和beanName两个参数。如果传入name带有“&”
//此时会做处理
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
接着我们继续往下看,进入getObjectForBeanInstance方法,进入到AbstractAutowireCapableBeanFactory类中getObjectForBeanInstance方法。
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
String currentlyCreatedBean = this.currentlyCreatedBean.get();
if (currentlyCreatedBean != null) {
registerDependentBean(beanName, currentlyCreatedBean);
}
//
return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
}
调用父类的getObjectForBeanInstance方法,我们可以看到会将我们调用context.getBean(“dbFactoryBean”)里的name,和处理后的beanName都传入,
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.
//此处会判断name是否带有“&”,如果带有就会进入此方法,返回FactoryBean实例。
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) {
//如果不带有“&”,会进入此处然后调用getObjectFromFactoryBean获取bean
// 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);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
public static boolean isFactoryDereference(@Nullable String name) {
return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
}
接下来我们可以看下getObjectFromFactoryBean方法。
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//如果是单例,会把对象放在缓存里,每次取的对象都是一样
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
// 从缓存里获取对象
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
//代码执行会进入此处
object = doGetObjectFromFactoryBean(factory, beanName);
//省略部分代码
}
然后进入doGetObjectFromFactoryBean方法,我们接着往下看,就会一目了然。
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<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//此时就会调用getObject()方法
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
记不记得我们自定义的FactoryBean里实现的getObject方法。这时就会调用此方法,然后生成返回我们创建的对象,也就是FactoryBeanUser 。如果加上“&”符号,我们就会直接返回我们实现的FactoryBean对象,也就是DbFactoryBean。