聊聊工廠bean和bean工廠有什么同異,先說結(jié)論
- bean工廠:不是bean,在spring中一般指的是DefaultListableBeanFactory對(duì)象,管理和維護(hù)spring中所有的bean
- 工廠bean:一種特殊的bean,在xml文件中配置的颤霎,用來生成新的bean的加工廠,通過getObject()方法可以獲取其生產(chǎn)的新bean,如果想獲取該工廠bean本身友酱,需要使用類似于
getBean("&" + beanName)
的樣式晴音。
demo
先來個(gè)小demo,具體學(xué)習(xí)和了解下如何使用工廠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");
// 生成工廠類生成的具體實(shí)體類缔杉,值的是studentFactory生成的類
System.out.println(student.toString());
StudentFactoryBean studentFactoryBean = (StudentFactoryBean) applicationContext.getBean("&studentFactory");
// 名字加了一個(gè)& 獲取的是studentFactory本身
System.out.println(studentFactoryBean.toString());
}
}
<bean name="studentFactory" class="com.demo.StudentFactoryBean" />
如上述代碼所述锤躁,我們自定義繼承了AbstractFactoryBean抽象類,并實(shí)現(xiàn)了幾個(gè)方法或详,便于生成具體的Student類
執(zhí)行結(jié)果也如設(shè)想的一般系羞,分別打印各自對(duì)象的toString,不過className并沒有被自動(dòng)注解上
源碼分析
以前的學(xué)習(xí)我們已經(jīng)知道了在refresh已經(jīng)完成了對(duì)xml配置的bean的實(shí)例化操作了。如下圖當(dāng)還未執(zhí)行g(shù)etBean("studentFactory")操作時(shí)霸琴,studentFactory和對(duì)應(yīng)的實(shí)體類都已經(jīng)完成了實(shí)例化操作(這點(diǎn)是需要關(guān)注的點(diǎn))
接下來我們就在回過頭看看refresh的操作是如何完成實(shí)例化的椒振。
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()) {
// 不是抽象類 是單例類型同時(shí)不是懶加載的beandefinition
if (isFactoryBean(beanName)) {
// 如果是工廠bean(針對(duì)beanName對(duì)應(yīng)的class類型匹配判斷)
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
// 調(diào)用getBean("&" + beanName)操作,返回的factory是工廠bean實(shí)例
// 這樣在這個(gè)bean實(shí)例中梧乘,存儲(chǔ)著映射的具體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 中獲取已經(jīng)處理好的single 實(shí)例化對(duì)象
if (sharedInstance != null && args == null) {
// single已經(jīng)有數(shù)據(jù)了,而且參數(shù)也沒有宋下,生成真正的對(duì)象bean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
if (isPrototypeCurrentlyInCreation(beanName)) {
// 如果當(dāng)前的beanName在prototype的創(chuàng)建中,則拋出異常
throw new BeanCurrentlyInCreationException(beanName);
}
// 獲取當(dāng)前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);
// 得到當(dāng)前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);
// 把每一個(gè)必須依賴的bean注冊(cè)好学歧,并進(jìn)行實(shí)例化操作
}
}
// 到這里就完成了一個(gè)對(duì)象實(shí)例化之前的操作了,現(xiàn)在需要?jiǎng)?chuàng)建具體的對(duì)象
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對(duì)象
// 獲取真正的實(shí)例對(duì)象各吨,返回
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());
}
}
// 強(qiáng)轉(zhuǎn)類型為T
return (T) bean;
}
AbstractAutowireCapableBeanFactory 文件 真正創(chuàng)建對(duì)象的方法
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 對(duì)象枝笨,依次去修改對(duì)應(yīng)的bean信息
// 這樣就可以再對(duì)BeanDefinition 進(jìn)行修改處理了
// 而且!=已选横浑!自動(dòng)注入值就是在這里通過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));
// 判斷是否是正在處理當(dāng)前這個(gè)single對(duì)象,而且允許循環(huán)引用
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注入值徙融,其實(shí)并沒有注入絕對(duì)的值,而是注入的相關(guān)數(shù)據(jù)瑰谜,在populated的時(shí)候才是完成真正的值注入
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
// 這一步很關(guān)鍵欺冀,重點(diǎn)關(guān)注下面貼出來的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 {
// 調(diào)用afterPropertiesSet 方法,完成對(duì)bean的singletonInstance實(shí)例化
((InitializingBean) bean).afterPropertiesSet();
}
}
...
}
AbstractFactoryBean 文件
public void afterPropertiesSet() throws Exception {
if (isSingleton()) {
this.initialized = true;
this.singletonInstance = createInstance();
// 相當(dāng)關(guān)鍵的一步H浴R!2吃纭职车!調(diào)用createInstance
this.earlySingletonInstance = null;
}
}
如圖所示,在執(zhí)行initializeBean之前時(shí),完成了對(duì)象的實(shí)例化悴灵,還會(huì)繼續(xù)進(jìn)行初始化bean操作
執(zhí)行initializeBean 之后扛芽,已經(jīng)填充了singletonInstance 對(duì)象了,其包含的是工廠生成的bean數(shù)據(jù)
完成整個(gè)的refresh操作之后称勋,其實(shí)所有的未懶加載的bean都已經(jīng)完成的實(shí)例化胸哥,工廠bean對(duì)應(yīng)的具體bean也被保存在工廠bean中。
接下來講講在完成實(shí)例化之后赡鲜,調(diào)用getBean獲取工廠bean實(shí)例以及工廠bean本身的細(xì)節(jié)
- getBean("studentFactory")
- getBean("&studentFactory")
1空厌、老套路來到了doGetBean方法,得出name的原始beanName值
2、從singletonObjects找確認(rèn)存在該值
3银酬、進(jìn)入到getObjectForBeanInstance方法
4嘲更、如果想要返回的是工廠bean本身,而且還不為null揩瞪,直接返回(也就是getBean("&studentFactory")操作)
5赋朦、從factoryBeanObjectCache確認(rèn)是否存在對(duì)應(yīng)的值
如果有,意味著存在這個(gè)對(duì)應(yīng)的值李破,直接返回(也就是多次getBean("studentFactory")操作)
沒有宠哄,需要getObjectFromFactoryBean這個(gè)方法,往factoryBeanObjectCache填充新的實(shí)例
image.png
這里需要注意的是存儲(chǔ)的value是工廠bean關(guān)聯(lián)的真實(shí)bean直接返回(也就是首次執(zhí)行g(shù)etBean("studentFactory")操作)
不過最后還有個(gè)問題嗤攻,就是最后生成的該對(duì)象Student并沒有為className注入值,通過上面的實(shí)現(xiàn)毛嫉,壓根沒有自動(dòng)注解的那段操作,而是在自定義的工廠bean中通過createInstance方法返回的妇菱,所以肯定是沒有值的承粤。