javax.annotation

# JSR250规范

1.JSR-250是什么?
  JSR-250主要围绕着“资源”的使用预定义了一些注解(Annotation),JSR-250相关的注解全部在javax.annotation和javax.security包中,包括:资源定义和权限控制。 像我们经常用到的@Resource、@PostConstruct、@PreDestroy、@Generated等都属于这个规范中定义的注解。该规范并没有提供具体的实现方式,仅仅是提供了指导性的文档和几个注解,由具体的框架去实现。
2.JSR-250涉及到的注解为什么放在javax包下而不是java包下?
  javax此处的x就是extension,java最初设计者认为,这些功能并非java核心API,谁用谁实现,按照约定即可。可以知道上面列举的常用注解都不是Spring提供的, 而是Spring按照JSR规范实现这个注解对资源的约束。

# PostConstruct注解

# 定义

  @PostConstruct是由JSR-250规范提供的在javax.annotation包下的注解,由具体的框架按照给定规范或设计文档具体去实现,具体可以在javax.annotation.PostConstruct上看到接口doc。

# 作用

  通过@PostConstruct注解可以介入到bean的声明周期,在Bean初始化阶段做一些操作,处理一些业务;与之对应的有@PreDestroy注解, 相反是在bean销毁之前,通常处理关闭一些资源。

# 执行时机

  由注解的名称可以Post Construct是在构造方法后,但是在init方法后执行

# 前景

  这两个注解PreDestroy和PostConstruct在Java9之后就不推荐使用,在Java11版本要被移除,Spring也给出了可替代方案为实现InitializingBean和DisposableBean接口

# Spring实现方式

  BeanPostProcessor是Spring提供的扩展接口,类似于钩子函数,在bean初始化前后做一些处理

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;
	}
}
1
2
3
4
5
6
7
8
9
10

  上面两个方法分别在bean执行populated(填充属性)前后执行,任何实现了BeanPostProcessor接口并且注册在SpringIOC容器中处理器, 都会在bean装载属性的前后处理这个bean。
  回到@PostConstruct注解,CommonAnnotationBeanPostProcessor类就是其中一个实现类,并且是处理@PostConstruct和@PreDestroy注解 的,InitDestroyAnnotationBeanPostProcessor是CommonAnnotationBeanPostProcessor的父类,lifecycleMetadataCache缓存bean和bean中带有注解方法的对象。

	private class LifecycleMetadata {

		private final Class<?> targetClass;

		private final Collection<LifecycleElement> initMethods;

		private final Collection<LifecycleElement> destroyMethods;
	}
1
2
3
4
5
6
7
8

PreDestroy方法被调用的原理(PostConstruct同理)

	public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
		LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
        //反射调用
		metadata.invokeDestroyMethods(bean, beanName);
    }
1
2
3
4
5