Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Analysis of Aware injection Source Code of Spring

2025-04-11 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)05/31 Report--

This article introduces the relevant knowledge of "Aware injection source code analysis of Spring". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Aware injection

When using Spring, we use our own Bean to implement BeanNameAware interface, BeanFactoryAware interface, etc., and rely on the container to help us inject the name of the current Bean or Bean factory, and the initializeBean method implemented by its code:

Protected Object initializeBean (final String beanName, final Object bean, RootBeanDefinition mbd) {

If (System.getSecurityManager ()! = null) {

AccessController.doPrivileged (new PrivilegedAction () {

Public Object run () {

InvokeAwareMethods (beanName, bean)

Return null

}

}, getAccessControlContext ()

}

Else {

InvokeAwareMethods (beanName, bean)

}

Object wrappedBean = bean

If (mbd = = null | |! mbd.isSynthetic ()) {

WrappedBean = applyBeanPostProcessorsBeforeInitialization (wrappedBean, beanName)

}

Try {

InvokeInitMethods (beanName, wrappedBean, mbd)

}

Catch (Throwable ex) {

Throw new BeanCreationException (

(mbd! = null? Mbd.getResourceDescription (): null)

BeanName, "Invocation of init method failed", ex)

}

If (mbd = = null | |! mbd.isSynthetic ()) {

WrappedBean = applyBeanPostProcessorsAfterInitialization (wrappedBean, beanName)

}

Return wrappedBean

}

Take a look at the implementation of line 5 above:

Private void invokeAwareMethods (final String beanName, final Object bean) {

If (bean instanceof BeanNameAware) {

((BeanNameAware) bean) .setBeanName (beanName)

}

If (bean instanceof BeanClassLoaderAware) {

((BeanClassLoaderAware) bean) .setBeanClassLoader (getBeanClassLoader ())

}

If (bean instanceof BeanFactoryAware) {

((BeanFactoryAware) bean) .setBeanFactory (AbstractAutowireCapableBeanFactory.this)

}

}

It is judged here that if bean is the implementation class of BeanNameAware interface, the setBeanName method will be called if bean is the implementation class of BeanClassLoaderAware interface, and the setBeanClassLoader method will be called if bean is the implementation class of BeanFactoryAware interface. If it is the implementation class of BeanFactoryAware interface, the setBeanFactory method will be called to inject the corresponding attribute value.

Call the postProcessBeforeInitialization method of BeanPostProcessor

The above initializeBean method takes a look at the 16-line implementation:

Public Object applyBeanPostProcessorsBeforeInitialization (Object existingBean, String beanName)

Throws BeansException {

Object result = existingBean

For (BeanPostProcessor beanProcessor: getBeanPostProcessors ()) {

Result = beanProcessor.postProcessBeforeInitialization (result, beanName)

If (result = = null) {

Return result

}

}

Return result

}

Iterate through each BeanPostProcessor interface implementation and call the postProcessBeforeInitialization method. The timing of the call to this interface will be summarized later. Here is a brief mention of the code.

Call initialization method

Line 20 of the initializeBean method, call the initialization method of Bean, and take a look at the implementation:

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 () {

Public Object run () throws Exception {

(InitializingBean) bean) .afterPropertiesSet ()

Return null

}

}, getAccessControlContext ()

}

Catch (PrivilegedActionException pae) {

Throw pae.getException ()

}

}

Else {

(InitializingBean) bean) .afterPropertiesSet ()

}

}

If (mbd! = null) {

String initMethodName = mbd.getInitMethodName ()

If (initMethodName! = null & & (isInitializingBean & & "afterPropertiesSet" .equals (initMethodName)) & &

! mbd.isExternallyManagedInitMethod (initMethodName)) {

InvokeCustomInitMethod (beanName, bean, mbd)

}

}

}

See, the code does two things:

1. First determine whether Bean is the implementation class of InitializingBean. If so, convert Bean to InitializingBean and call the afterPropertiesSet () method directly.

2. Try to get init-method, if any, call initMethod through reflection

Therefore, the two methods have their own advantages and disadvantages: the way to implement the InitializingBean interface is more efficient because the init-method method is called through reflection; on the other hand, the init-method method is less coupled to Spring. Which method is used to call the initialization method depends on your personal preference.

Call the postProcessAfterInitialization method of BeanPostProcessor

The last step, line 29 of the initializeBean method:

Public Object applyBeanPostProcessorsAfterInitialization (Object existingBean, String beanName)

Throws BeansException {

Object result = existingBean

For (BeanPostProcessor beanProcessor: getBeanPostProcessors ()) {

Result = beanProcessor.postProcessAfterInitialization (result, beanName)

If (result = = null) {

Return result

}

}

Return result

}

Also iterate through the BeanPostProcessor and call the postProcessAfterInitialization method. So for the BeanPostProcessor method, let's summarize:

1. The method of each configured Bean is called when initializing each BeanPostProcessor.

2. Call the postProcessBeforeInitialization method after Bean property setting and Aware setting

3. Call the postProcessAfterInitialization method after initializing the method call

Register the Bean that needs to execute the destroy method

Next, take a look at line 83 of the top doCreateBean method, registerDisposableBeanIfNecessary (beanName, bean, mbd), which completes the last thing you do to create a Bean: register the Bean that needs to execute the destroy method.

Take a look at the implementation of the method:

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))

}

Else {

/ / A bean with a custom scope...

Scope scope = this.scopes.get (mbd.getScope ())

If (scope = = null) {

Throw new IllegalStateException ("No Scope registered for scope'" + mbd.getScope () + "'")

}

Scope.registerDestructionCallback (beanName

New DisposableBeanAdapter (bean, beanName, mbd, getBeanPostProcessors (), acc))

}

}

}

In line 3, the first judgment is that it must not be prototype (prototype), and the second is that the implementation of the requiresDestruction method is:

Protected boolean requiresDestruction (Object bean, RootBeanDefinition mbd) {

Return (bean! = null & &

(bean instanceof DisposableBean | | mbd.getDestroyMethodName ()! = null | |

HasDestructionAwareBeanPostProcessors ())

}

To register a destroy method, Bean needs to meet at least one of the following three conditions:

(1) Bean is the implementation class of DisposableBean, so execute the interface method destroy () of DisposableBean.

(2) there is a configuration destroy-method attribute in the Bean tag. The method specified by the destroy-method configuration is executed at this time.

(3) the implementation class of DestructionAwareBeanPostProcessor interface is held in the BeanFactory corresponding to Bean, and the interface method postProcessBeforeDestruction of DestructionAwareBeanPostProcessor is executed at this time.

If one of the above three conditions is met, the container will register to destroy the Bean. The method of registering Bean is very simple, as implemented by the registerDisposableBean method:

Public void registerDisposableBean (String beanName, DisposableBean bean) {

Synchronized (this.disposableBeans) {

This.disposableBeans.put (beanName, bean)

}

}

When the container is destroyed, it traverses the disposableBeans and executes the destruction method one by one.

This is the end of the content of "Aware injection source code analysis of Spring". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report