聊聊工廠bean和bean工廠有什么同異,先說結論
- bean工廠:不是bean,在spring中一般指的是DefaultListableBeanFactory對象,管理和維護spring中所有的bean
- 工廠bean:一種特殊的bean,在xml文件中配置的,用來生成新的bean的加工廠,通過getObject()方法可以獲取其生產的新bean,如果想獲取該工廠bean本身,需要使用類似于
getBean("&" + beanName)
的樣式。
demo
先來個小demo,具體學習和了解下如何使用工廠bean
public class StudentFactoryBean extends AbstractFactoryBean<Object> {
@Override
public Class<?> getObjectType() {
return Student.class;
}
@Override
protected Object createInstance() throws Exception {
return new Student("factoryDemo", 18);
}
@Override
public String toString() {
return "StudentFactoryBean";
}
}
public class Bootstrap {
public static void main(String[] args){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
new String[]{"context.xml"}, false);
applicationContext.setAllowBeanDefinitionOverriding(false);
applicationContext.refresh();
Student student = (Student)applicationContext.getBean("studentFactory");
// 生成工廠類生成的具體實體類,值的是studentFactory生成的類
System.out.println(student.toString());
StudentFactoryBean studentFactoryBean = (StudentFactoryBean) applicationContext.getBean("&studentFactory");
// 名字加了一個& 獲取的是studentFactory本身
System.out.println(studentFactoryBean.toString());
}
}
<bean name="studentFactory" class="com.demo.StudentFactoryBean" />
如上述代碼所述,我們自定義繼承了AbstractFactoryBean抽象類,并實現了幾個方法,便于生成具體的Student類
執行結果也如設想的一般,分別打印各自對象的toString,不過className并沒有被自動注解上
源碼分析
以前的學習我們已經知道了在refresh已經完成了對xml配置的bean的實例化操作了。如下圖當還未執行getBean("studentFactory")操作時,studentFactory和對應的實體類都已經完成了實例化操作(這點是需要關注的點)
接下來我們就在回過頭看看refresh的操作是如何完成實例化的。
DefaultListableBeanFactory 文件
public void preInstantiateSingletons() throws BeansException {
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 得到合并parentBean的beandefinition bd
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 不是抽象類 是單例類型同時不是懶加載的beandefinition
if (isFactoryBean(beanName)) {
// 如果是工廠bean(針對beanName對應的class類型匹配判斷)
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
// 調用getBean("&" + beanName)操作,返回的factory是工廠bean實例
// 這樣在這個bean實例中,存儲著映射的具體bean
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);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
AbstractBeanFactory 文件
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
// 如果是"&" + beanName,那么beanName就是去掉&的值
Object bean;
Object sharedInstance = getSingleton(beanName);
// 從singletonObjects 中獲取已經處理好的single 實例化對象
if (sharedInstance != null && args == null) {
// single已經有數據了,而且參數也沒有,生成真正的對象bean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
if (isPrototypeCurrentlyInCreation(beanName)) {
// 如果當前的beanName在prototype的創建中,則拋出異常
throw new BeanCurrentlyInCreationException(beanName);
}
// 獲取當前bean工廠的父親工廠
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 如果有父親工廠,而且還未處理
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 得到當前beandefinition的依賴元素
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);
getBean(dep);
// 把每一個必須依賴的bean注冊好,并進行實例化操作
}
}
// 到這里就完成了一個對象實例化之前的操作了,現在需要創建具體的對象
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
// 得到的sharedInstance 是工廠類 StudentBeanFactory對象
// 獲取真正的實例對象,返回
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
// 強轉類型為T
return (T) bean;
}
AbstractAutowireCapableBeanFactory 文件 真正創建對象的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// 獲取到所有的MergedBeanDefinitionPostProcessor 對象,依次去修改對應的bean信息
// 這樣就可以再對BeanDefinition 進行修改處理了
// 而且?。?!自動注入值就是在這里通過AutowiredAnnotationBeanPostProcessor類完成的
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
// 判斷是否是正在處理當前這個single對象,而且允許循環引用
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
// 完成值的真正填充,注意在上面說過使用AutowiredAnnotationBeanPostProcessor注入值,其實并沒有注入絕對的值,而是注入的相關數據,在populated的時候才是完成真正的值注入
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
// 這一步很關鍵,重點關注下面貼出來的invokeInitMethods 方法
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
....
return exposedObject;
}
// ====== 分割線 ======
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 調用afterPropertiesSet 方法,完成對bean的singletonInstance實例化
((InitializingBean) bean).afterPropertiesSet();
}
}
...
}
AbstractFactoryBean 文件
public void afterPropertiesSet() throws Exception {
if (isSingleton()) {
this.initialized = true;
this.singletonInstance = createInstance();
// 相當關鍵的一步?。。。。≌{用createInstance
this.earlySingletonInstance = null;
}
}
如圖所示,在執行initializeBean之前時,完成了對象的實例化,還會繼續進行初始化bean操作
執行initializeBean 之后,已經填充了singletonInstance 對象了,其包含的是工廠生成的bean數據
完成整個的refresh操作之后,其實所有的未懶加載的bean都已經完成的實例化,工廠bean對應的具體bean也被保存在工廠bean中。
接下來講講在完成實例化之后,調用getBean獲取工廠bean實例以及工廠bean本身的細節
- getBean("studentFactory")
- getBean("&studentFactory")
1、老套路來到了doGetBean方法,得出name的原始beanName值
2、從singletonObjects找確認存在該值
3、進入到getObjectForBeanInstance方法
4、如果想要返回的是工廠bean本身,而且還不為null,直接返回(也就是getBean("&studentFactory")操作)
5、從factoryBeanObjectCache確認是否存在對應的值
如果有,意味著存在這個對應的值,直接返回(也就是多次getBean("studentFactory")操作)
沒有,需要getObjectFromFactoryBean這個方法,往factoryBeanObjectCache填充新的實例
image.png
這里需要注意的是存儲的value是工廠bean關聯的真實bean直接返回(也就是首次執行getBean("studentFactory")操作)
不過最后還有個問題,就是最后生成的該對象Student并沒有為className注入值,通過上面的實現,壓根沒有自動注解的那段操作,而是在自定義的工廠bean中通過createInstance方法返回的,所以肯定是沒有值的。