One 、 Preface
- Springboot Source code analysis is a big project , Study the code line by line , It's going to be boring , It's not easy to stick to it .
- We don't want to be big and complete , But try to study a little knowledge point at a time , Finally, the sand becomes a tower , This is our springboot A glimpse of the source code series .
Two 、ApplicationContextAware
- Suppose we want to use a bean, If it's in @Component Under class , Direct use @Autowired Just quote
- Suppose we want to use... In a static method , You can't use the above method
- You may want to use new Bean() The way ,new One , But this bean Inside @Autowired Citation doesn't work
- If there is a static global ApplicationContext Just fine , use spring Ability acquisition bean: ApplicationContext.getBean(clazz)
- ApplicationContextAware That's the use
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
public interface Aware {
}
Let's write an implementation class :
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
private static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
}
- adopt setApplicationContext, hold applicationContext Assign to a local static variable
- adopt ApplicationContext Of getBean You can use any bean The ability to
3、 ... and 、 Source code analysis
We enter SpringApplication Of run Method :
public ConfigurableApplicationContext run(String... args) {
...
try {
...
refreshContext(context);
...
}
catch (Throwable ex) {
...
}
...
return context;
}
We enter refreshContext(context) Inside :
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
destroyBeans();
cancelRefresh(ex);
throw ex;
}
finally {
resetCommonCaches();
}
}
}
This refresh yes spring The core method of , It will be used many times in the future , It's too much , We only focus on one method this time :
- prepareBeanFactory(beanFactory);
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
...
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
...
}
}
We see first prepareBeanFactory(beanFactory):
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
...
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
...
}
Let's take a look at this addBeanPostProcessor Method
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// Remove from old position, if any
this.beanPostProcessors.remove(beanPostProcessor);
// Track whether it is instantiation/destruction aware
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
// Add to end of list
this.beanPostProcessors.add(beanPostProcessor);
}
- First remove, Again add
- beanPostProcessors Is a thread safe list: CopyOnWriteArrayList
- Let's look down new ApplicationContextAwareProcessor(this), Be careful :this yes ApplicationContext
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
/**
* Create a new ApplicationContextAwareProcessor for the given context.
*/
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
}
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof 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;
}
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);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
- Construction method , hold applicationContext Set to local variables
- How to implement the interface :postProcessBeforeInitialization, It will be used in callback , It's mainly about checking permissions
- The bottom invokeAwareInterfaces It's a private core callback method , According to different types , There are different callbacks
We see that in addition to ApplicationContextAware, There are others aware, in total 6 individual
- EnvironmentAware: environment variable
- EmbeddedValueResolverAware: Value resolver
- ResourceLoaderAware: Resource loader
- ApplicationEventPublisherAware: Event publisher
- MessageSourceAware: Information processor
- ApplicationContextAware:spring Containers
For example, we want to use global environment variables , There is EnvironmentAware, Want to use spring I'll use it when I'm in trouble ApplicationEventPublisherAware, wait
- The source has been found ,ApplicationContextAwareProcessor When was it executed ?
- This is more troublesome , Let's just open a section later and see it in detail .
Welcome to WeChat official account. : Fengji , More technology learning sharing .