关于@
⽬录
@PostConstruct、init-method、afterPropertiesSet() 执⾏顺序
@PostConstruct 标注的⽅法在何时被谁调⽤
init-method、afterPropertiesSet() 的调⽤
顺序的确定
@PostConstruct、init-method、afterPropertiesSet() 执⾏顺序
想要知道 @PostConstruct、init-method、afterPropertiesSet() 的执⾏顺序,只要搞明⽩它们各⾃在什么时候被谁调⽤就⾏了。程序版本:Spring Boot 2.3.5.RELEASE
准备好要验证的材料:
public class Foo implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet()");
}
@PostConstruct
public void init() {
System.out.println("@PostConstruct");
}
private void initMethod() {
System.out.println("initMethod()");
}
}
@Configuration
public class FooConfiguration {
@Bean(initMethod = "initMethod")
public Foo foo() {
return new Foo();
}
}
执⾏启动类,可以看到在控制台中输出:
@PostConstruct
afterPropertiesSet()
initMethod()
说明执⾏顺序是:@PostConstruct、afterPropertiesSet()、init-method
接下来将跟着源码来了解为什么是这个顺序。
@PostConstruct 标注的⽅法在何时被谁调⽤
⾸先,在 init() 中打个断点,然后以 debug 的⽅式启动项⽬,得到下⾯的调⽤栈:
init:23, Foo (com.xurk.init.foo)
invoke0:-1, NativeMethodAccessorImpl (flect)
invoke:62, NativeMethodAccessorImpl (flect)
invoke:43, DelegatingMethodAccessorImpl (flect)
invoke:498, Method (flect)
invoke:389, InitDestroyAnnotationBeanPostProcessor$LifecycleElement (org.springframework.beans.factory.annotation)
invokeInitMethods:333, InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata (org.springframework.beans.factory.annotation) postProcessBeforeInitialization:157, InitDestroyAnnotationBeanPostProcessor (org.springframework.beans.factory.annotation) applyBeanPostProcessorsBeforeInitialization:415, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support) initializeBean:1786, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:594, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:516, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:324, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 2103763750 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$169)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:322, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:202, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:897, DefaultListableBeanFactory (org.springframework.beans.factory.support)
refresh:143, ServletWebServerApplicationContext (org.springframework.boot.t)
refresh:758, SpringApplication (org.springframework.boot)
refresh:750, SpringApplication (org.springframework.boot)
refreshContext:405, SpringApplication (org.springframework.boot)
run:315, SpringApplication (org.springframework.boot)
run:1237, SpringApplication (org.springframework.boot)
run:1226, SpringApplication (org.springframework.boot)
main:14, InitApplication (com.xurk.init)
从上往下看,跳过使⽤ flect 的⽅法,进⼊到第6⾏。
public void invoke(Object target) throws Throwable {
ReflectionUtils.hod);
}
很明显,这⾥是在通过反射调⽤某个对象的⼀个⽅法,并且这个“某个对象”就是我们定义的 Foo的实例对象了。
那么这⾥的 method ⼜是在什么时候进⾏赋值的呢?
invoke(...) 全路径是:
org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.LifecycleElement#invoke
并且 LifecycleElement 有且只有⼀个显⽰声明并且带参数的构造器,这个要传⼊构造器的参数正是 invoke(...) 使⽤的那个 Method 对象。
接下来就是查⼀下,是谁在 new LifecycleElement 。
于是定位到:
org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#buildLifecycleMetadata
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
ptyLifecycleMetadata;
}
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()) {
}
}
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
currDestroyMethods.add(new LifecycleElement(method));
if (logger.isTraceEnabled()) {
}
}
});
initMethods.addAll(0, currInitMethods);
destroyMethods.addAll(currDestroyMethods);
targetClass = Superclass();
}
while (targetClass != null && targetClass != Object.class);
return (initMethods.isEmpty() && destroyMethods.isEmpty() ? ptyLifecycleMetadata :
new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
第15-26⾏是在通过反射判断⽅法上是否存在某个注解,如果是的话就加到⼀个集合中,在最后⽤于构建 LifecycleMetadata 实例。
在这⾥因为我们要查的是被赋值的内容,所以在使⽤IDE进⾏查时只要关注 write 相关的内容就⾏了。
到这⾥,已经知道了是在 CommonAnnotationBeanPostProcessor 的构造器中进⾏ set 的,也就是当创建CommonAnnotationBeanPostProcessor 实例的时候就会进⾏赋值,并且 CommonAnnotationBeanPostProcessor 是InitDestroyAnnotationBeanPostProcessor 的⼦类。
并且,CommonAnnotationBeanPostProcessor 构造器中调⽤的 setInitAnnotationType 其实是它⽗类的⽅法,实际是对InitDestroyAnnotationBeanPostProcessor 的实例的 initAnnotationType 字段进⾏赋值。
到这⾥已经可以明确 buildLifecycleMetadata(...) 中判断的正是 @PostConstruct。
再回到buildLifecycleMetadata(...) ,查看其使⽤的 doWithLocalMethods(...) 的实现。
public static void doWithLocalMethods(Class<?> clazz, MethodCallback mc) {
Method[] methods = getDeclaredMethods(clazz, false);
spring framework面试题for (Method method : methods) {
try {
mc.doWith(method);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException("Not allowed to access method '" + Name() + "': " + ex);
}
}
}
很简单,通过反射获得类的所有⽅法,然后调⽤⼀个函数接⼝的⽅法,这个函数接⼝的实现就是判断⽅法是不是被 @PostConstruct 标注,如果被标注的话放到⼀个名字叫 currInitMethods 的集合中。
看到这⾥或许你已经意识到了, @PostConstruct 可以标注多个⽅法,并且因为反射获取⽅法时是根据声明顺序的、 currInitMethods 是 ArrayList,两者之间的顺序是⼀样的。
好了,被 @PostConstruct 标注的⽅法已经到放到集合中了,将被⽤来构建 LifecycleMetadata 实例了。
buildLifecycleMetadata(...) ⽅法返回⼀个 LifecycleMetadata 实例,这个返回值中包含传⼊Class实例中得到的所有被 @PostConstruct 标注的 Method 实例,接下来要看看是谁在调⽤ buildLifecycleMetadata(...) ⽅法,看看它是怎么⽤的?
追溯到 findLifecycleMetadata(...) ⽽ findLifecycleMetadata(...) ⼜有好⼏处被调⽤。
查看最早得到的⽅法调⽤栈,查到postProcessBeforeInitializatio(...) ,它⼜是再被谁调⽤?
init:23, Foo (com.xurk.init.foo)
invoke0:-1, NativeMethodAccessorImpl (flect)
invoke:62, NativeMethodAccessorImpl (flect)
invoke:43, DelegatingMethodAccessorImpl (flect)
invoke:498, Method (flect)
invoke:389, InitDestroyAnnotationBeanPostProcessor$LifecycleElement (org.springframework.beans.factory.annotation)
invokeInitMethods:333, InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata (org.springframework.beans.factory.annotation) postProcessBeforeInitialization:157, InitDestroyAnnotationBeanPostProcessor (org.springframework.beans.factory.annotation) applyBeanPostProcessorsBeforeInitialization:415, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
initializeBean:1786, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
跟着⽅法调⽤栈,我们来到
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization @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;
}
在这个⽅法,遍历 BeanPostProcessors 集合并执⾏每个 BeanPostProcessor 的 postProcessBeforeInitialization(...) ⽅法。
**那么 getBeanPostProcessors() 中的内容⼜是在什么时候放进去的呢?都有哪些内容?**可以通过 AnnotationConfigUtils和CommonAnnotationBeanPostProcessor 查,这⾥就不再赘述了。
查 applyBeanPostProcessorsBeforeInitialization(...) 的调⽤者,来到
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (SecurityManager() != 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 ? ResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
顾名思义,在这个⽅法中对 Bean 进⾏初始化。是在被注⼊前⼀定要经过的过程,到这⾥被 @PostConstruct 标注的⽅法执⾏已经完成了。⾄于这个⽅法谁调⽤可以⾃⼰查看调⽤栈。
init-method、afterPropertiesSet() 的调⽤
细⼼的朋友可能已经发现了在 initializeBean(...) 中有调⽤到⼀个叫做 invokeInitMethods(...) 的⽅法。
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()) {
}
if (SecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
Exception();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && Class() != NullBean.class) {
String initMethodName = InitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
BeanDefinition是Bean定义的⼀个抽象。类似于在Java中存在Class类⽤于描述⼀个类,⾥⾯有你定义的 Bean 的各种信息。
在第4⾏,判断是不是 InitializingBean,如果是的话会进⾏类型强转,然后调⽤ afterPropertiesSet()。
在第26⾏,获得到⾃定义初始化⽅法的名字,然后在第30⾏调⽤ invokeCustomInitMethod 执⾏完成。
顺序的确定
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (SecurityManager() != 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 ? ResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论