作者:shihuaping0918@163.com轉(zhuǎn)載請(qǐng)注明作者
scope是用來(lái)定義spring如何創(chuàng)建bean的。bean默認(rèn)是singleton涂乌,在容器中只有一個(gè)實(shí)例械筛,名字就提示了敢艰,是設(shè)計(jì)模式里的單件,或者叫單例俊抵。還有一種是prototype谁不,可以創(chuàng)建多個(gè)實(shí)例。對(duì)于singleton徽诲,無(wú)所謂生命周期刹帕,反正容器在它就在,頂多是關(guān)注一下它是在哪里實(shí)例化的谎替。只有prototype類型的才有真正意義上的生命周期偷溺。這篇文章就帶大家來(lái)看一下prototype類型的bean的生命周期。
prototype類型的bean可以通過(guò)應(yīng)用上下文獲取時(shí)創(chuàng)建钱贯,也可以在注入時(shí)創(chuàng)建挫掏。先看一下應(yīng)用上下文獲取時(shí),它是怎么創(chuàng)建的秩命。因?yàn)樗蟹椒ㄗ鳛槿肟谖竟玻雌饋?lái)比較直觀。在之前的文章中弃锐,其實(shí)已經(jīng)分析過(guò)應(yīng)用上下文相關(guān)的代碼了袄友,也就是applicationContext相關(guān)的代碼,其中有一個(gè)類對(duì)register factory的方法做了一層封裝霹菊,用意就是在調(diào)register factory方法時(shí)剧蚣,先做一下判斷。下面直接去AbstractApplicationContext里看方法。
@Override
public Object getBean(String name) throws BeansException { //看它就好了
assertBeanFactoryActive(); //同下
return getBeanFactory().getBean(name);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
assertBeanFactoryActive(); //同上
return getBeanFactory().getBean(name, requiredType);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
assertBeanFactoryActive(); //同上
return getBeanFactory().getBean(name, args);
}
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
assertBeanFactoryActive(); //同上
return getBeanFactory().getBean(requiredType);
}
@Override
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
assertBeanFactoryActive(); //同上
return getBeanFactory().getBean(requiredType, args);
}
前面的文章里介紹過(guò)getBeanFactory獲取的是DefaultListableBeanFactory券敌,到這個(gè)類里去找getBean方法,getBean位于AbstractBeanFactory里面柳洋。
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
注意參數(shù)待诅,要關(guān)注參數(shù)值,后續(xù)的代碼看起來(lái)才有重點(diǎn)熊镣。
/**
* Return an instance, which may be shared or independent, of the specified bean.
* @param name the name of the bean to retrieve
* @param requiredType the required type of the bean to retrieve
* @param args arguments to use when creating a bean instance using explicit arguments
* (only applied when creating a new instance as opposed to retrieving an existing one)
* @param typeCheckOnly whether the instance is obtained for a type check,
* not for actual use
* @return an instance of the bean
* @throws BeansException if the bean could not be created
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//requiredType=null,args=null,typeCheckOnly=false卑雁,注意參數(shù)
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) { //我們要看的是prototype,single這一段跳過(guò)
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 + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else { //代碼進(jìn)了這里,非singleton的類型
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
//如果有父類廠绪囱,且當(dāng)前類廠中沒(méi)有這個(gè)bean测蹲,就到父類廠中查找,不進(jìn)這個(gè)條件里面
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) { //args==null鬼吵,不進(jìn)
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) { //requiredType==null扣甲,不進(jìn)
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) { //注意進(jìn)來(lái)的參數(shù)typeCheckOnly==false
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) { //創(chuàng)建父類,屬性成員類齿椅,等等
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) { //循環(huán)依賴琉挖,拋異常
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) { //singleton類型跳過(guò)
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) { //我們想要的prototype代碼流程,直接創(chuàng)建一個(gè)新的bean
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName); //tls中添加當(dāng)前創(chuàng)建的bean信息
prototypeInstance = createBean(beanName, mbd, args); //在這里創(chuàng)建了bean
}
finally {
afterPrototypeCreation(beanName); //tls中清除當(dāng)前創(chuàng)建的bean信息
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else { // session/request類型
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, () -> {
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 && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
在createBrean中涣脚,會(huì)實(shí)例化bean示辈,并且初始化,填充好bean的成員屬性遣蚀,詳細(xì)分析見(jiàn)《spring源碼分析6----bean字段or成員變量填充》矾麻,這篇已經(jīng)對(duì)bean的實(shí)例化做了詳細(xì)的分析。prototype的bean使用完以后芭梯,會(huì)由垃圾回收對(duì)它進(jìn)行處理险耀。
上面講的是getBean顯式獲取bean,下面講注入的時(shí)候玖喘,prototyp類型的bean是怎么處理的胰耗。要接著上面的createBean繼續(xù)分析,實(shí)例化以后就是成員的填充芒涡,這里就會(huì)用到注入了柴灯。
在前面分析bean實(shí)例化的時(shí)候已經(jīng)涉及到類初始化,成員的填充费尽,這里只是前面文章內(nèi)容的延伸赠群。createBean調(diào)用doCreateBean。而doCreateBean會(huì)調(diào)用populateBean旱幼,填充bean查描。
/**
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param bw the BeanWrapper with bean instance
*/
@SuppressWarnings("deprecation") // for postProcessPropertyValues
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) { //實(shí)例為null
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { //做一些預(yù)處理
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); //獲取屬性
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs); //按名稱注入
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs); //按類型注入,看類型吧,比較快
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs); //填充在這里完成
}
}
去看autowireByType
/**
* Abstract method defining "autowire by type" (bean properties by type) behavior.
* <p>This is like PicoContainer default, in which there must be exactly one bean
* of the property type in the bean factory. This makes bean factories simple to
* configure for small namespaces, but doesn't work as well as standard Spring
* behavior for bigger applications.
* @param beanName the name of the bean to autowire by type
* @param mbd the merged bean definition to update through autowiring
* @param bw the BeanWrapper from which we can obtain information about the bean
* @param pvs the PropertyValues to register wired objects with
*/
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
if (Object.class != pd.getPropertyType()) {
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter); //查找屬性對(duì)應(yīng)的依賴
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
這個(gè)方法當(dāng)中冬三,resolveDependency會(huì)調(diào)用doResolveDependency匀油。
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) { //我們要看創(chuàng)建過(guò)程,這里跳過(guò)
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) { //匹配到多個(gè)勾笆,這里不用看
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else { //精準(zhǔn)匹配到一個(gè)
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) { //如果匹配到的是類敌蚜,這里我們要關(guān)注
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); //就是在這里實(shí)例化的
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
在doresolveDependency方法中,對(duì)于prototype的bean窝爪,會(huì)去創(chuàng)建一個(gè)實(shí)例弛车,看一看descriptor.resolveCondidate
/**
* Resolve the specified bean name, as a candidate result of the matching
* algorithm for this dependency, to a bean instance from the given factory.
* <p>The default implementation calls {@link BeanFactory#getBean(String)}.
* Subclasses may provide additional arguments or other customizations.
* @param beanName the bean name, as a candidate result for this dependency
* @param requiredType the expected type of the bean (as an assertion)
* @param beanFactory the associated factory
* @return the bean instance (never {@code null})
* @throws BeansException if the bean could not be obtained
* @since 4.3.2
* @see BeanFactory#getBean(String)
*/
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
return beanFactory.getBean(beanName); //這就是文章一開(kāi)始分析的方法
}
總結(jié)一下,populateBean填充bean實(shí)例的屬性蒲每,它先調(diào)用autowireByType獲取屬性的名稱纷跛,還有屬性要填充的值,在本篇中邀杏,這個(gè)值指的就是被prototype修飾的bean贫奠。這個(gè)值是通過(guò)getBean(name)來(lái)獲取的,而文章前面分析過(guò)getBean(name)對(duì)于prototype修飾的bean望蜡,是直接創(chuàng)建一個(gè)實(shí)例叮阅。從代碼來(lái)看,在自動(dòng)注入的情況下泣特,prototype修飾的bean總是會(huì)被重新創(chuàng)建浩姥。
寫(xiě)在最后:接單,有后臺(tái)活java/cpp/lua/go聯(lián)系shihuaping0918@163.com状您。不上班了也要有點(diǎn)收入才行勒叠。