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.