BeanFactory与FactoryBean的区别以及FactoryBean的详解
都是对象工厂,用来创建对象。如果使用BeanFactory
的接口,那么必须要严格遵守spring bean
的生命周期接口:从实例化,到初始化,到invokeAwareMethod,invokeInitMethod,before,after
此流程非常复杂且麻烦,如果需要一种更加便捷的方式创建,所有有了FactoryBean
这个接口,不需要遵循此创建顺序
FactoryBean详解
methods
- getObjectType:返回类型
- isSingleton:判断是否单例
- getObject:直接返回对象
isSingleton
true
当使用FactoryBean
接口来创建对象的时候,一共会创建两个对象,一个实现FactoryBean
的对象,一个FactoryBean
对象getObject
返回的对象
getObject
的对象会在首次调用返回Bean
的时候进行获取且缓存到BeanFactroy
中的factoryBeanInstanceCache
缓存对象中,而FactoryBean
则会缓存到BeanFactroy
的一级缓存singletonObjects
中
由上可知:当isSingleton
返回true
时,两个对象都是由Spring
来进行管理的
false
BeanFacoty
中仅缓存了实现了FactoryBean
的对象,而每次获取getObject
返回的对象时,都是返回的一个新的对象信息
FactoryBean与getObject中对象的获取方法
FactoryBean
通过BeanName
加上&
前缀获取
getObject
直接根据BeanName
进行获取
测试
User
package com.armin.self_factoryBean;
public class User {
private Integer age;
private String username;
public User() {
}
public User(Integer age, String username) {
this.age = age;
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", username='" + username + '\'' +
'}';
}
}
MyFactoryBean
package com.armin.self_factoryBean;
import org.springframework.beans.factory.FactoryBean;
public class MyFactoryBean implements FactoryBean<User> {
@Override
public User getObject() throws Exception {
return new User(18, "ARMIN");
}
@Override
public Class<?> getObjectType() {
return User.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
armin-self-factoryBean.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myFactoryBean" class="com.armin.self_factoryBean.MyFactoryBean"/>
</beans>
Test
package com.armin.self_factoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("armin-self-factoryBean.xml");
User bean = (User) context.getBean("myFactoryBean");
MyFactoryBean bean2 = (MyFactoryBean) context.getBean("&myFactoryBean");
System.out.println(bean);
System.out.println(bean2);
}
}
console
User{age=18, username='ARMIN'}
com.armin.self_factoryBean.MyFactoryBean@35cabb2a
当isSingleton = true
bean
,bean1
为相同对象
当isSingleton = false
bean
,bean1
为不同的对象
getBean执行步骤
- org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.String)
- org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
- org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
- org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance
- org.springframework.beans.factory.support.AbstractBeanFactory#getMergedLocalBeanDefinition(第一次获取)
- org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getCachedObjectForFactoryBean(非第一次获取)
此处描述不够清晰后续进行补充