As mentioned earlier in combing through the source code for SpringBean creation, draw a flow chart of the interfaces involved. Now fill in the hole. Meanwhile, I was mainly focused on Spring’s code logic (so I can’t read it myself now). In this rereading series, we start with the overall structure, and if it is not particularly important to the logic, we do not focus on some of the details of the logic.
A, DefaultListableBeanFactory
1, structure,
For SpringMVC Bean container core class is the implementation of the DefaultListableBeanFactory, then we’ll look at the hierarchy
The inheritance of class we need to pay attention to DefaultSingletonBeanRegistry, AbstractBeanFactory, including DefaultSingletonBeanRegistry class is a singleton Bean of the deposit, AbstractBeanFactory is the entire logical processing of getting a Bean.
Let’s look directly at the process of obtaining beans. The sequence diagram drawn below is not a standard sequence diagram, but just an overview of the process, so if you want to draw a standard sequence diagram, please study the resources.
Ii. Stage 1 (Extend direct object instance creation)
Can be generated directly by the InstantiationAwareBeanPostProcessor interface beans here, but the Spring annotations is that the interface is generally for use within the Spring framework, and is not recommended to use this interface directly. If must expand, the recommended InstantiationAwareBeanPostProcessorAdapter interface
public abstract class InstantiationAwareBeanPostProcessorAdapter implements SmartInstantiationAwareBeanPostProcessor {
Copy the code
You can see the SmartInstantiationAwareBeanPostProcessor interface is realized.
1. Extensible interface
This stage can expand interface ` ` InstantiationAwareBeanPostProcessor, official recommends InstantiationAwareBeanPostProcessorAdapter `
2. Flow chart
This is the first stage of getting the Bean, and you can see that it passesInstantiationAwareBeanPostProcessor
To generate the Bean, and you can see that it calls the other extension interfaceBeanPostProcessor
The interface.
3. Introduction of the overall process
Class
requiredType). Class
requiredType (Class
requiredType) can also be used as the input parameter, but it will be converted to name
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
Copy the code
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
return getBean(requiredType, (Object[]) null);
}
Copy the code
2) We can see that it calls the doGetBean method
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly)
Copy the code
3) Then you can see that if it is a singleton, it calls the getSingleton method to get the corresponding Bean instance, but it is created by the createBean method
if (mbd.isSingleton()) {
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);
throwex; }}); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }Copy the code
. 4), then through mbdToUse prepareMethodOverrides hasMethodOverrides () call () method to determine processing < lookup method – > tag.
@Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { RootBeanDefinition mbdToUse = mbd; Class<? > resolvedClass = resolveBeanClass(mbd, beanName); . // Prepare method overrides. try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean ! = null) { return bean; } } catch (Throwable ex) { ........ } try { Object beanInstance = doCreateBean(beanName, mbdToUse, args); return beanInstance; }... }Copy the code
public void prepareMethodOverrides(a) throws BeanDefinitionValidationException {
// Check that lookup methods exists.
if (hasMethodOverrides()) {
Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
synchronized (overrides) {
for(MethodOverride mo : overrides) { prepareMethodOverride(mo); }}}}protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
intcount = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName()); .else if (count == 1) {
// Mark override as not overloaded, to avoid the overhead of arg type checking.
mo.setOverloaded(false); }}Copy the code
5), and then through resolveBeforeInstantiation think you could get to a Bean.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
Copy the code
6), through the hasInstantiationAwareBeanPostProcessors () method to look have InstantiationAwareBeanPostProcessors interface implementation class, if you have, Call the interface postProcessBeforeInstantiation method, if the interface has create return Bean, call the BeanPostProcessor interface postProcessAfterInitialization method again, This completes the creation of the Bean.
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if(! Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.
if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<? > targetType = determineTargetType(beanName, mbd);if(targetType ! =null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if(bean ! =null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean ! =null);
}
return bean;
}
Copy the code
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class
beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if(result ! =null) {
returnresult; }}}return null;
}
Copy the code
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
Copy the code
We see if it is at this stage by InstantiationAwareBeanPostProcessor interface produced Bean returned, Then it will only call the BeanPostProcessor interface postProcessAfterInitialization method, won’t call its such as some Aware interface.
If above did not produce by InstantiationAwareBeanPostProcessor Bean, will then to invoke doCreateBean (beanName mbdToUse, args) method.
3. Stage 2 (Extend constructor to create instance)
1. Extensible interface
Here are the interfaces that can be extended:
1. Supplier to BeanDefinition
BeanDefinition <factory-method> factory method
3, SmartInstantiationAwareBeanPostProcessor, this also is recommended adapter InstantiationAwareBeanPostProcessorAdapter to expand
2. Flow chart
3. Overall process
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {... instanceWrapper = createBeanInstance(beanName, mbd, args); }finalObject bean = instanceWrapper.getWrappedInstance(); Class<? > beanType = instanceWrapper.getWrappedClass(); .// Allow post-processors to modify the merged bean definition.
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; }}...// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch(Throwable ex) { .......... }...return exposedObject;
}
Copy the code
CreateBeanInstance (beanName, MBD, args); createBeanInstance(beanName, MBD, args); For example, through the final Object bean = instanceWrapper. GetWrappedInstance (); Get this comb out.
Now let’s look at the createBeanInstance method
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.Class<? > beanClass = resolveBeanClass(mbd, beanName); . Supplier<? > instanceSupplier = mbd.getInstanceSupplier();if(instanceSupplier ! =null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
if(mbd.getFactoryMethodName() ! =null) {
returninstantiateUsingFactoryMethod(beanName, mbd, args); }...// Need to determine the constructor...Constructor<? >[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if(ctors ! =null|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || ! ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
Copy the code
@Nullable
publicSupplier<? > getInstanceSupplier() {return this.instanceSupplier;
}
Copy the code
protected BeanWrapper obtainFromSupplier(Supplier
instanceSupplier, String beanName) {... Object instance; instance = instanceSupplier.get(); . BeanWrapper bw =new BeanWrapperImpl(instance);
initBeanWrapper(bw);
return bw;
}
Copy the code
As you can see, it will first generate an instance object through Supplier.
3) If the Supplier is not extended by the BeanDefinition. I’m going to determine if it has a FactoryMethodName, and I’m going to create the instance using the factory method.
if (mbd.getFactoryMethodName() ! = null) { return instantiateUsingFactoryMethod(beanName, mbd, args); }Copy the code
protected BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
Copy the code
public BeanWrapper instantiateUsingFactoryMethod(
final String beanName, final RootBeanDefinition mbd, @Nullable final Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw); .try{ Object beanInstance; .else {
beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);
}
bw.setBeanInstance(beanInstance);
returnbw; }... }Copy the code
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, final Method factoryMethod, @Nullable Object... args) {... Object result = factoryMethod.invoke(factoryBean, args);if (result == null) {
result = new NullBean();
}
returnresult; }... }Copy the code
<bean id="listInstance" class="org.springframework.beans.factory.xml.FactoryMethods"
factory-method="listInstance"/>
Copy the code
private static List listInstance(a) {
return Collections.EMPTY_LIST;
}
Copy the code
These are the processes that generate instances through the FactoryMethod method.
4) If it does not extend the factory method as well, then the constructor will formally generate the Bean instance. But there will be an extension interface.
(5), we first look at determineConstructorsFromBeanPostProcessors beanClass, beanName) method
@Nullable
protectedConstructor<? >[] determineConstructorsFromBeanPostProcessors(@NullableClass<? > beanClass, String beanName)throws BeansException {
if(beanClass ! =null && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceofSmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; Constructor<? >[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);if(ctors ! =null) {
returnctors; }}}}return null;
}
Copy the code
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
this.beanPostProcessors.remove(beanPostProcessor);
this.beanPostProcessors.add(beanPostProcessor);
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true; }}Copy the code
Can see here provides SmartInstantiationAwareBeanPostProcessor interface for your development to build a custom constructor. To call its determineCandidateConstructors method.
@Nullable
defaultConstructor<? >[] determineCandidateConstructors(Class<? > beanClass, String beanName)throws BeansException {
return null;
}
Copy the code
6), if there is no use SmartInstantiationAwareBeanPostProcessor interface returns a custom constructor, you call instantiateBean (beanName, MBD) method to call itself a default constructor.
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if(System.getSecurityManager() ! =null) {
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
getInstantiationStrategy().instantiate(mbd, beanName, parent),
getAccessControlContext());
}
else {
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); }}Copy the code
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if(! bd.hasMethodOverrides()) { .........finalClass<? > clazz = bd.getBeanClass();if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface"); }... constructorToUse = clazz.getDeclaredConstructor(); .return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
returninstantiateWithMethodInjection(bd, beanName, owner); }}Copy the code
Here you can see if there is a way to rewrite, will be to produce the Bean through additional carding, namely CglibSubclassingInstantiationStrategy class, now we are in the midst of a SimpleInstantiationStrategy classes.
public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy {
Copy the code
4. Process summary
There are three main points at this stage to generate instance objects:
1) Generate instances through Supplier (if any custom extensions exist)
<factory-method> <factory-method> (if there is a custom extension)
3), by constructing methods: one is through SmartInstantiationAwareBeanPostProcessor interface to return the custom constructors, if there is no custom, via the default constructor to create the Bean instance.
Stage 3 (Extend instance properties & Instance modification)
1. Flow chart
2. Overall process
At this point, a Bean instance object without attribute assignment has been created through the previous second phase, and it is now time to populate the Bean’s attribute content.
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {...finalObject bean = instanceWrapper.getWrappedInstance(); Class<? > beanType = instanceWrapper.getWrappedClass(); .// Allow post-processors to modify the merged bean definition.
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; }}...// Initialize the bean instance.
Object exposedObject = bean;
try{ populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); }...// Register bean as disposable.
try{ registerDisposableBeanIfNecessary(beanName, bean, mbd); }...return exposedObject;
}
Copy the code
1), applyMergedBeanDefinitionPostProcessors (MBD, beanType, beanName)
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class
beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceofMergedBeanDefinitionPostProcessor) { MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp; bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); }}}Copy the code
Can see here is to call * * * * postProcessMergedBeanDefinition MergedBeanDefinitionPostProcessor interface method to expand. This method has a RootBeanDefinition input, so you can use that RootBeanDefinition to manipulate some properties.
2)、populateBean(beanName, mbd, instanceWrapper)
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {...if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if(! ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation =false;
break; }}}}if(! continueWithPropertyPopulation) {return; }...boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
booleanneedsDepCheck = (mbd.getDependencyCheck() ! = RootBeanDefinition.DEPENDENCY_CHECK_NONE); .if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
........
if(pvs ! =null) {
// Set the attributes of bwapplyPropertyValues(beanName, mbd, bw, pvs); }}Copy the code
Can see here mainly through expanding InstantiationAwareBeanPostProcessor interface. Its postProcessAfterInstantiation method can determine to down to attribute assignment or not. If it can call its postProcessPropertyValues method again, this interface can operate the PropertyValues.
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
Copy the code
@Nullable
default PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
Copy the code
3)、initializeBean(beanName, exposedObject, mbd)
This method initializes the Bean instance, essentially running some other extended interface. At this point, we’ve already assigned the corresponding property
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {... invokeAwareMethods(beanName, bean); } Object wrappedBean = bean;if (mbd == null| |! mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); }try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw newBeanCreationException( (mbd ! =null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null| |! mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); }return wrappedBean;
}
Copy the code
InvokeAwareMethods (Final String beanName, final Object bean)
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if(bcl ! =null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); }}if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); }}}Copy the code
Here you can see the BeanNameAware, BeanClassLoaderAware, and BeanFactoryAware interfaces that handle extensions.
5), applyBeanPostProcessorsBeforeInitialization (wrappedBean, beanName)
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
Copy the code
Began to call the BeanPostProcessor interface postProcessBeforeInitialization method here.
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
Copy the code
In this interface you can handle the Bean instance yourself.
6)、invokeInitMethods(beanName, wrappedBean, mbd)
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null| |! mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {...else{ ((InitializingBean) bean).afterPropertiesSet(); }}if(mbd ! =null&& bean.getClass() ! = NullBean.class) { String initMethodName = mbd.getInitMethodName();if(StringUtils.hasLength(initMethodName) && ! (isInitializingBean &&"afterPropertiesSet".equals(initMethodName)) && ! mbd.isExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd); }}}Copy the code
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable { String initMethodName = mbd.getInitMethodName(); .else {
try{ ReflectionUtils.makeAccessible(initMethod); initMethod.invoke(bean); . }}Copy the code
This is to run initMethod, which can be extended using the InitializingBean interface or handled with the
tag (also equivalent to the @postconstruct annotation). Note that the name of init-method cannot be afterPropertiesSet, which means it cannot have the same name as the method of the InitializingBean interface, otherwise you cannot run custom init-method methods.
7), applyBeanPostProcessorsAfterInitialization (wrappedBean, beanName)
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
Copy the code
Can be seen in by running Aware interface – > BeanPostProcessor interface postProcessBeforeInitialization () – > InitializingBean interface, It will go to the last call the BeanPostProcessor interface postProcessAfterInitialization ().
(8), registerDisposableBeanIfNecessary beanName, bean, MBD)
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) { AccessControlContext acc = (System.getSecurityManager() ! =null ? getAccessControlContext() : null);
if(! mbd.isPrototype() && requiresDestruction(bean, mbd)) {if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
Copy the code
public static boolean hasApplicableProcessors(Object bean, List<BeanPostProcessor> postProcessors) {
if(! CollectionUtils.isEmpty(postProcessors)) {for (BeanPostProcessor processor : postProcessors) {
if (processor instanceof DestructionAwareBeanPostProcessor) {
DestructionAwareBeanPostProcessor dabpp = (DestructionAwareBeanPostProcessor) processor;
if (dabpp.requiresDestruction(bean)) {
return true; }}}}return false;
}
Copy the code
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {...public void registerDisposableBean(String beanName, DisposableBean bean) {
synchronized (this.disposableBeans) {
this.disposableBeans.put(beanName, bean); }}Copy the code
Finally here can also DestructionAwareBeanPostProcessor interface to determine its need to be added to the disposableBeans.
At this point, the creation of the Bean instance is complete.
Let’s look at Bean destruction
V. Stage IV (Destruction)
1, add to disposableBeans stage judgment
About the destruction of Bean, it is useful to the upper DestructionAwareBeanPostProcessor interface, but its InitDestroyAnnotationBeanPostProcessor interface is used to management, We have this method above for requiresDestruction(Object Bean, RootBeanDefinition MBD) to determine whether it needs to be added to disposableBeans.
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
return(bean.getClass() ! = NullBean.class && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors())))); }Copy the code
You can see that it has three or conditions:
1) One is to judge whether to implement the DisposableBean interface
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {
return true; }... }Copy the code
public static boolean hasApplicableProcessors(Object bean, List<BeanPostProcessor> postProcessors) {
if(! CollectionUtils.isEmpty(postProcessors)) {for (BeanPostProcessor processor : postProcessors) {
if (processor instanceof DestructionAwareBeanPostProcessor) {
DestructionAwareBeanPostProcessor dabpp = (DestructionAwareBeanPostProcessor) processor;
if (dabpp.requiresDestruction(bean)) {
return true; }}}}return false;
}
Copy the code
public class InitDestroyAnnotationBeanPostProcessor
implements DestructionAwareBeanPostProcessor.MergedBeanDefinitionPostProcessor.PriorityOrdered.Serializable {...@Override
public boolean requiresDestruction(Object bean) {
return findLifecycleMetadata(bean.getClass()).hasDestroyMethods();
}
Copy the code
2), the second is through InitDestroyAnnotationBeanPostProcessor rewrite requiresDestruction method.
public boolean hasDestroyMethods(a) {
Collection<LifecycleElement> checkedDestroyMethods = this.checkedDestroyMethods; Collection<LifecycleElement> destroyMethodsToUse = (checkedDestroyMethods ! =null ? checkedDestroyMethods : this.destroyMethods);
return! destroyMethodsToUse.isEmpty(); }Copy the code
private class LifecycleMetadata {...private final Collection<LifecycleElement> initMethods;
private finalCollection<LifecycleElement> destroyMethods; .public LifecycleMetadata(Class
targetClass, Collection
initMethods, Collection
destroyMethods)
{
this.targetClass = targetClass;
this.initMethods = initMethods;
this.destroyMethods = destroyMethods;
}
Copy the code
This class also has initMethods.
private LifecycleMetadata buildLifecycleMetadata(finalClass<? > clazz) {... ReflectionUtils.doWithLocalMethods(targetClass, method -> {if(initAnnotationType ! =null) {
if(method.getAnnotation(initAnnotationType) ! =null) {
LifecycleElement element = newLifecycleElement(method); currInitMethods.add(element); . }if(destroyAnnotationType ! =null) {
if(method.getAnnotation(destroyAnnotationType) ! =null) {... }}); initMethods.addAll(0, currInitMethods); destroyMethods.addAll(currDestroyMethods); .return new LifecycleMetadata(clazz, initMethods, destroyMethods);
}
Copy the code
public CommonAnnotationBeanPostProcessor(a) {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
}
Copy the code
public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {
this.initAnnotationType = initAnnotationType;
}
public void setDestroyAnnotationType(Class<? extends Annotation> destroyAnnotationType) {
this.destroyAnnotationType = destroyAnnotationType;
}
Copy the code
This is the destroy-method method.
2. Destruction stage
public void destroySingletons(a) {
synchronized (this.singletonObjects) {
this.singletonsCurrentlyInDestruction = true;
}
String[] disposableBeanNames;
synchronized (this.disposableBeans) {
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
}
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
Copy the code
You can see that you are going through the Bean instance that you added to disposableBeans earlier, and then destroying it using the destroySingleton method.
public void destroySingleton(String beanName) {...synchronized (this.disposableBeans) {
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
destroyBean(beanName, disposableBean);
}
Copy the code
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {...// Actually destroy the bean now...
if(bean ! =null) {
try{ bean.destroy(); }... }Copy the code
And here we can see it’s gonna be forced to DisposableBean, because if you have destroy-Method alone that doesn’t have an interface it’s already been handled and in order to DisposableBeanAdapter, the adapter mode is used.
At this point, some of the interfaces involved in the entire singleton Bean creation and destruction process are combed out.