1.ApplicationContext的初始化以及銷毀
對于BeanFactory也有一個初始化和銷毀關閉的過程,比如程式設計式的容器如下:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainApp.class);
構造方法如下:
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
refresh是IoC的開始,方法如下:
@Override
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);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory 是為啟動過程做了一些準備工作,為容器配置了Classloader、PropertyEditor、BeanPostProcessor、Environment環境等資訊,進而為容器啟動做了必要的準備工作。
/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
同時,容器在關閉時也會做一系列的操作。在doClose中,先發出容器關閉的信号、然後将Bean逐個關閉,最後關閉容器自身。org.springframework.context.support.AbstractApplicationContext#doClose:
protected void doClose() {
// Check whether an actual close attempt is necessary...
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isDebugEnabled()) {
logger.debug("Closing " + this);
}
LiveBeansView.unregisterApplicationContext(this);
try {
// Publish shutdown event.
publishEvent(new ContextClosedEvent(this));
}
catch (Throwable ex) {
logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
}
// Stop all Lifecycle beans, to avoid delays during individual destruction.
if (this.lifecycleProcessor != null) {
try {
this.lifecycleProcessor.onClose();
}
catch (Throwable ex) {
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
}
}
// Destroy all cached singletons in the context's BeanFactory.
destroyBeans();
// Close the state of this context itself.
closeBeanFactory();
// Let subclasses do some final clean-up if they wish...
onClose();
// Reset local application listeners to pre-refresh state.
if (this.earlyApplicationListeners != null) {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Switch to inactive.
this.active.set(false);
}
}
2. Bean的生命周期
容器的實作是通過IoC來管理Bean的生命周期來實作的。Spring IoC容器在對Bean的生命周期進行管理時提供了Bean生命周期的各個時間點的回調。IoC中Bean的生命周期如下:
(1)Bean執行個體的建立
(2)為Bean執行個體設定屬性
(3)調用Bean的初始化方法
(4)應用可以通過IoC容器使用Bean
(5)容器關閉時,調用Bean的銷毀方法
在上一節IoC依賴注入過程中研究了Bean執行個體的建立、設定屬性、調用Bean的初始化。
(1) 執行個體的建立實際就是反射或者CGlib代理生成對象
(2) 設定屬性實際就是依賴注入
(3) Bean的初始化方法: 依賴注入完成之後調用初始化initializeBean方法
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
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;
}
private void invokeAwareMethods(String beanName, 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);
}
}
}
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
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);
}
}
}
-1》在調用初始化方法之前,會先調用invokeAwareMethods 一系列的ware接口實作,把相關的BeanName、BeanClassLoader以及BeanFactory注入到Bean中去。
-2》接着調用applyBeanPostProcessorsBeforeInitialization 處理BeanPostProcessor的postProcessBeforeInitialization 初始化之前邏輯。需要注意 @PostConstruct 注解聲明的方法也是在這個階段被調用的,其對應的BeanPostProcessor 是CommonAnnotationBeanPostProcessor
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
CommonAnnotationBeanPostProcessor 處理邏輯如下:
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor繼承自父類的postProcessBeforeInitialization方法
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 找到PostConstruct 聲明的方法
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
// 反射調用
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
尋找注解聲明的方法如下:
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
if (this.lifecycleMetadataCache == null) {
// Happens after deserialization, during destruction...
return buildLifecycleMetadata(clazz);
}
// Quick check on the concurrent map first, with minimal locking.
LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
synchronized (this.lifecycleMetadataCache) {
metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
metadata = buildLifecycleMetadata(clazz);
this.lifecycleMetadataCache.put(clazz, metadata);
}
return metadata;
}
}
return metadata;
}
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
List<LifecycleElement> initMethods = new ArrayList<>();
List<LifecycleElement> destroyMethods = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
}
}
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
currDestroyMethods.add(new LifecycleElement(method));
if (logger.isTraceEnabled()) {
logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
}
}
});
initMethods.addAll(0, currInitMethods);
destroyMethods.addAll(currDestroyMethods);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new LifecycleMetadata(clazz, initMethods, destroyMethods);
}
CommonAnnotationBeanPostProcessor 構造裡定義了對應的注解:
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
}
-3》接着調用invokeInitMethods方法,會看到啟動afterPropertiesSet 的過程,當然這需要Bean實作InitializingBean 接口,對應的初始化處理可以在InitializingBean 接口的afterPropertiesSet 方法實作,同樣是對Bean的一個回調。
最後還會判斷是否有initMethod,如果有那麼通過invokeCustomInitMethod 直接調用最終完成對Bean的初始化。
protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd)
throws Throwable {
String initMethodName = mbd.getInitMethodName();
Assert.state(initMethodName != null, "No init method set");
Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
if (initMethod == null) {
if (mbd.isEnforceInitMethod()) {
throw new BeanDefinitionValidationException("Could not find an init method named '" +
initMethodName + "' on bean with name '" + beanName + "'");
}
else {
if (logger.isTraceEnabled()) {
logger.trace("No default init method named '" + initMethodName +
"' found on bean with name '" + beanName + "'");
}
// Ignore non-existent default lifecycle methods.
return;
}
}
if (logger.isTraceEnabled()) {
logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
}
Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(methodToInvoke);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
() -> methodToInvoke.invoke(bean), getAccessControlContext());
}
catch (PrivilegedActionException pae) {
InvocationTargetException ex = (InvocationTargetException) pae.getException();
throw ex.getTargetException();
}
}
else {
try {
ReflectionUtils.makeAccessible(methodToInvoke);
methodToInvoke.invoke(bean);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
invokeCustomInitMethod 方法調用中,首先得到Bean定義的initMethod方法,然後通過JDK的反射得到Method對象,直接調用在Bean定義中聲明的初始化方法。
-4》 調用applyBeanPostProcessorsAfterInitialization 方法處理BeanPostProcessor 的postProcessAfterInitialization 代碼邏輯。 需要注意PreDestroy 注解生命的會在這個裡面做處理,對應的Processor是CommonAnnotationBeanPostProcessor
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
(4) IoC容器使用Bean
(5) Bean的銷毀
上面容器的銷毀中 destroyBeans 是銷毀Bean,經過一系列的調用會調到:org.springframework.beans.factory.support.DisposableBeanAdapter#destroy
@Override
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) this.bean).destroy();
return null;
}, this.acc);
}
else {
((DisposableBean) this.bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
首先調用 postProcessBeforeDestruction,然後調用Bean的destroy方法,最後是對Bean的自定義銷毀方法的調用,和前面初始化的過程類型。
測試如下:
UserDao:
package cn.qz.user;
import org.springframework.stereotype.Component;
@Component
public class UserDao {
public void test1() {
}
}
UserService:
package cn.qz.user;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
//@Component
//@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
//@Lazy
public class UserService implements InitializingBean, DisposableBean, BeanNameAware {
// 構造
public UserService() {
System.out.println("=============UserService=====");
}
@Autowired
public void setUserDao(UserDao userDao) {
System.out.println("cn.qz.user.UserService.setUserDao====userDao");
}
// aware 接口
@Override
public void setBeanName(String name) {
System.out.println("====setBeanName====" + name);
}
@PostConstruct
public void PostConstruct() {
System.out.println("PostConstruct =============");
}
// InitializingBean
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("====afterPropertiesSet====");
}
// initMethod
public void initMethod() {
System.out.println("====initMethod====");
}
@PreDestroy
public void PreDestroy() {
System.out.println("PreDestroy =============");
}
// DisposableBean
@Override
public void destroy() throws Exception {
System.out.println("====destroy====");
}
// destroyMethod
public void destroyMethod() {
System.out.println("====destroyMethod====");
}
}
配置類:
package cn.qz.user;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanConfiguration {
@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
public UserService userService() {
return new UserService();
}
}
程式設計式IoC如下:
package cn.qz;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
//@Import({ImpConfiguration.class})
//@EnableAspectJAutoProxy
public class App {
public static void main(String[] args) {
//在指定目錄下生成動态代理類,我們可以反編譯看一下裡面到底是一些什麼東西
// System.setProperty("cglib.debugLocation", "F:/proxy");
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(App.class);
applicationContext.close();
}
}
結果:
=============UserService=====
cn.qz.user.UserService.setUserDao====userDao
====setBeanName====userService
PostConstruct =============
====afterPropertiesSet====
====initMethod====
PreDestroy =============
====destroy====
====destroyMethod====
總結:其生命周期圖如下:
(1) Aware 接口的實作順序為:BeanNameAware-》BeanClassLoaderAware-》BeanFactoryAware
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
private void invokeAwareMethods(String beanName, 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);
}
}
}
(2) ApplicationContextAwareProcessor 是一個特殊的BeanPostProcessor, 裡面主要是增加了ApplicationContext 的一些相關Aware
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(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
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 Aware) {
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);
}
}
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
(3) 在容器的BeanPostProcessor 中有幾個全局的非常有用的類:(Spring 預設的一些BeanPostProcessor)
3. BeanPostProcessor 的實作
BeanPostProcessor是一個Bean的後置處理器,它可以監聽容器觸發的事件。将它向IoC容器注冊後,容器中管理的Bean具備了接收IoC容器事件回調的能力。接口提供兩個方法,一個是postProcessBeforeInitialization 在Bean的初始化之前提供回調入口;還有一個是postProcessAfterInitialization 在Bean的初始化之後提供回調入口。這兩個回調都和容器管理Bean的生命周期相關。回調方法的參數都是一樣的,分别是Bean的執行個體化對象和Bean的名字。
如下:
package org.springframework.beans.factory.config;
import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
兩個方法的調用都是在doCreateBean方法的initializeBean 方法調用時調用
(1) org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 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;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
(2) org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
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;
}
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
從上面代碼可以看到,這兩個Bean後置處理器定義的接口方法,一前一後,圍繞着Bean定義的init-method方法調用。
測試如下:
package qz;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
/**
* @author: 喬利強
* @date: 2021/2/19 15:47
* @description:
*/
@Component
public class MyPostProcessor implements BeanPostProcessor {
// Bean的初始化之前提供回調入口
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("====postProcessBeforeInitialization====");
}
return bean;
}
// Bean的初始化之後提供回調入口
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("====postProcessAfterInitialization====");
}
return bean;
}
}
結果:
=============UserService=====
====setBeanName====userService
====postProcessBeforeInitialization====
PostConstruct =============
====afterPropertiesSet====
====initMethod====
====postProcessAfterInitialization====
PreDestroy =============
====destroy====
====destroyMethod====
補充: BeanPostProcessor 的兩個方法的傳回值可以是以下三種情況
bean-不對IoC生成的bean做處理,原封不動的傳回
proxrTarget-代理對象。也就是生成Cglib代理或者是JDK代理對象。 這對于接口類型接收的對象是可以的。(AOP代理對象的生成也是在BeanPostProcessor 中傳回代理對象來修改引用完成的)
null 傳回一個空對象
4. Aware的使用
容器管理的Bean一般不需要了解容器的狀态和直接使用容器,但在某些情況下,是需要在Bean中直接對IoC容器操作的,這時候就需要設定對容器的感覺。SpringIoC容器也提供了該功能,通過特定的Aware接口實作。
在設定Bean的屬性之後,調用初始化回調方法之前,Spring會調用sware接口的setter方法。
org.springframework.context.support.ApplicationContextAwareProcessor 作為BeanPostProcessor 的實作,對一系列的aware 回調進行了調用
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(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
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 Aware) {
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);
}
}
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
ApplicationContextAwareProcessor 注入到Spring的時機是在org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory 準備IoC環境時。org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory 如下:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
測試:
package qz;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.*;
import org.springframework.core.io.ResourceLoader;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
//@Component
//@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
//@Lazy
public class UserService implements InitializingBean, DisposableBean, BeanNameAware, BeanFactoryAware, ApplicationContextAware, MessageSourceAware, ApplicationEventPublisherAware, ResourceLoaderAware {
// 構造
public UserService() {
System.out.println("=============UserService=====");
}
// BeanNameAware====可以在Bean中得到它在IoC容器中的Bean執行個體名稱
@Override
public void setBeanName(String name) {
System.out.println("====setBeanName====" + name);
}
// BeanFactoryAware====可以得到Bean所在的IoC容器,進而直接在Bean中石油IoC容器的服務
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("====beanFactory====" + beanFactory.getClass());
}
// ApplicationContextAware====可以在Bean得到Bean所在的應用上下文
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("====ApplicationContextAware====" + applicationContext.getClass());
}
// MessageSourceAware ==== 在Bean中得到消息源
@Override
public void setMessageSource(MessageSource messageSource) {
System.out.println("====setMessageSource====" + messageSource.getClass());
}
// ApplicationEventPublisherAware ==== 在Bean中得到應用上下文的事件釋出器,進而可以在Bean中釋出應用上下文的事件
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
System.out.println("====setApplicationEventPublisher====" + applicationEventPublisher.getClass());
}
// ResourceLoaderAware ==== 在Bean中得到ResourceLoader,進而在Bean中使用ResourceLoader 加載外部對應的Resource資源
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
System.out.println("====setResourceLoader====" + resourceLoader.getClass());
}
@PostConstruct
public void PostConstruct() {
System.out.println("PostConstruct =============");
}
// InitializingBean
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("====afterPropertiesSet====");
}
// initMethod
public void initMethod() {
System.out.println("====initMethod====");
}
@PreDestroy
public void PreDestroy() {
System.out.println("PreDestroy =============");
}
// DisposableBean
@Override
public void destroy() throws Exception {
System.out.println("====destroy====");
}
// destroyMethod
public void destroyMethod() {
System.out.println("====destroyMethod====");
}
}
結果:
=============UserService=====
====setBeanName====userService
====beanFactory====class org.springframework.beans.factory.support.DefaultListableBeanFactory
====setResourceLoader====class org.springframework.context.annotation.AnnotationConfigApplicationContext
====setApplicationEventPublisher====class org.springframework.context.annotation.AnnotationConfigApplicationContext
====setMessageSource====class org.springframework.context.annotation.AnnotationConfigApplicationContext
====ApplicationContextAware====class org.springframework.context.annotation.AnnotationConfigApplicationContext
====postProcessBeforeInitialization====
PostConstruct =============
====afterPropertiesSet====
====initMethod====
====postProcessAfterInitialization====
PreDestroy =============
====destroy====
====destroyMethod====
補充:FactoryBean 滿足Bean 的生命周期,建立、屬性注入、初始化(調用Aware接口、BeanPostProcessor.postProcessBeforeInitialization、InitializingBean.afterPropertiesSet、invokeCustomInitMethod、BeanPostProcessor.postProcessAfterInitialization)、使用、銷毀。但是FactoryBean 的getObject 方法生成的對象不會走生命流程。
并且在IoC 過程中初始化單例對象時不會建立對象工廠getObject 建立的對象,對象工廠生成的對象隻會在第一次使用getBean 擷取時才會建立。
我們知道對于factoryBean, &beanName 擷取factory 對象自身,beanName 擷取其生成的getObject 對象
測試:
Test 類:
package cn.qz.factorybean;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
public class Test implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, BeanClassLoaderAware {
public Test() {
System.out.println("Test=====0");
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("Test=====1");
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
System.out.println("Test=====2");
}
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
System.out.println("Test=====3");
}
}
TestFactoryBean:
package cn.qz.factorybean;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;
public class TestFactoryBean implements FactoryBean<Test>, ResourceLoaderAware, BeanClassLoaderAware, InitializingBean {
public TestFactoryBean() {
System.out.println("TestFactoryBean created===1");
}
@Override
public Test getObject() throws Exception {
return new Test();
}
@Override
public Class<?> getObjectType() {
return Test.class;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("TestFactoryBean created===2");
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
System.out.println("TestFactoryBean created===3");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("TestFactoryBean created===4");
}
}
主類:
package cn.qz;
import cn.qz.factorybean.Test;
import cn.qz.factorybean.TestFactoryBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;
@Import({TestFactoryBean.class})
public class App {
public App() {
System.out.println("App created ======");
}
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(App.class);
Test bean = applicationContext.getBean(Test.class);
System.out.println(bean);
applicationContext.close();
}
}
結果
App created ======
TestFactoryBean created===1
TestFactoryBean created===2
TestFactoryBean created===3
TestFactoryBean created===4
Test=====0
cn.qz.factorybean.Test@1b1473ab
applicationContext.getBean(Test.class);代碼跟蹤:
1》org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.Class<T>)
2》org.springframework.beans.factory.support.DefaultListableBeanFactory#getBean(java.lang.Class<T>)
3》org.springframework.beans.factory.support.DefaultListableBeanFactory#getBean(java.lang.Class<T>, java.lang.Object...)
4》org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveBean
5》org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveNamedBean(org.springframework.core.ResolvableType, java.lang.Object[], boolean)
org.springframework.beans.factory.support.DefaultListableBeanFactory#getBeanNamesForType(org.springframework.core.ResolvableType) 擷取合适的beanname
上面方法調用org.springframework.beans.factory.support.DefaultListableBeanFactory#getBeanNamesForType(java.lang.Class<?>, boolean, boolean) 擷取适用的beanName
上面方法調用org.springframework.beans.factory.support.DefaultListableBeanFactory#doGetBeanNamesForType 這裡周遊factorybean,調用 Class<?> getObjectType(); 根據這個類型進行類型的判斷
擷取的适用的beanName為:
6》 擷取到對應的beanName之後調用(beanName 是工廠的名稱,requiredType類型是工廠生成的對象類型)。org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String, java.lang.Class<T>, java.lang.Object...)
7》org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
首先擷取到對象工廠對象調用org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance
調用org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean 從對象工廠擷取對象
org.springframework.beans.factory.support.FactoryBeanRegistrySupport#doGetObjectFromFactoryBean 直接調用對象的getObject 方法