Aware interface

When we need to use some of the underlying components in Spring, we need to customize the bean to implement the corresponding Aware interface to obtain the underlying components, such as ApplicationContextAware, BeanFactoryAware, BeanNameAware, EnvironmentAware etc.

Implement the ApplicationContextAware interface to get the ApplicationContext

package main.beans;

/ * * *@author lgx
 * @date2020/12/13 plague *@desc* /
public class BeanB {

    private String id;

    private String name;

    private Integer age;

    public String getId(a) {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName(a) {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge(a) {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString(a) {
        return "BeanA{" +
                "id='" + id + '\' ' +
                ", name='" + name + '\' ' +
                ", age=" + age +
                '} ';
    }

package main.beans;

/ * * *@author lgx
 * @dateSprinkling 2020/12/13 *@desc* /
public class BeanA{

    private String name;

    private Integer age;

    public String getName(a) {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge(a) {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString(a) {
        return "BeanA{" +
                ", name='" + name + '\' ' +
                ", age=" + age +
                '} '; }}Copy the code

Define BeanC to implement the ApplicationContextAware interface

package main.beans;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.text.SimpleDateFormat;
import java.util.Date;

/ * * *@author lgx
 * @date2020/12/13 for *@desc* /
public class BeanC implements ApplicationContextAware {

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("Main. Beans. BeanC. SetApplicationContext execution");
        BeanA bean = applicationContext.getBean(BeanA.class);
        System.out.println("Get name from BeanA:"+ bean.getName()); }}Copy the code

Configure spring-config.xml to register three beans

    <bean id="beanC" class="main.beans.BeanC"></bean>
    <bean id="beanA" class="main.beans.BeanA">
        <property name="name" value="I am BeanA"></property>
        <property name="age" value="15"></property>
    </bean>

    <bean id="beanB" class="main.beans.BeanB">
        <property name="id" value="15"></property>
        <property name="name" value="I am BeanB"></property>
        <property name="age" value="15"></property>
    </bean>
Copy the code

The test results

package main.beans;

import org.springframework.context.support.ClassPathXmlApplicationContext;

/ * * *@author lgx
 * @dateSprinkling 2020/12/13 *@desc* /
public class Main {


    public static void main(String[] args) {

        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml"); }}Copy the code

Console output:

Main. Beans. BeanC. In the implementation for BeanA setApplicationContext initialization method of attributes: I am BeanA

Question: Why can we get applicationContext by implementing the ApplicationContextAware interface

ApplicationContextAwareProcessor

This will have to mention ApplicationContextAwareProcessor this class.

ApplicationContextAwareProcessor implements the BeanPostProcessor interface, we can know the interface in the Bean’s initialization to do some before and after operation. Then we see ApplicationContextAwareProcessor implementation method of the operation

@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
   if(! (beaninstanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
         bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
         bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
      return bean;
   }

   AccessControlContext acc = null;

   if(System.getSecurityManager() ! =null) {
      acc = this.applicationContext.getBeanFactory().getAccessControlContext();
   }

   if(acc ! =null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
         invokeAwareInterfaces(bean);
         return null;
      }, acc);
   }
   else {
      invokeAwareInterfaces(bean);
   }

   return bean;
}
Copy the code

You can see if the bean properties EnvironmentAware EmbeddedValueResolverAware, ResourceLoaderAware

, ApplicationEventPublisherAware MessageSourceAware ApplicationContextAware one of them will go

InvokeAwareInterfaces (bean) method, so let’s see how this method is implemented:

private void invokeAwareInterfaces(Object bean) {
   if (bean instanceof EnvironmentAware) {
      ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
   }
   if (bean instanceof EmbeddedValueResolverAware) {
      ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
   }
   if (bean instanceof ResourceLoaderAware) {
      ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
   }
   if (bean instanceof ApplicationEventPublisherAware) {
      ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
   }
   if (bean instanceof MessageSourceAware) {
      ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
   }
    // Here the setApplicationContext method of the custom bean is called and passed in
   if (bean instanceof ApplicationContextAware) {
      ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); }}Copy the code

At the end of the method, if the bean is of type ApplicationContextAware, the setApplicationContext method of the custom bean will be called and passed in to the applicationContext

So this is where the truth comes out, and you can try to make a breakpoint and see if you can get into this method.