优质博文:IT-BLOG-CN
一、简介
如果需要在生成对象时就完成某些初始化操作,而且这些初始化操作又依赖于依赖注入@Autowired
,那么就无法在构造函数中实现。为此,可以使用@PostConstruct
注解一个方法来完成初始化。@PostConstruct
注解的方法将会在依赖注入完成后被自动调用。类初始化调用顺序: Constructor >> @Autowired >> @PostConstruct
特点:
1、只有一个非静态方法能使用此注解;
2、被注解的方法不得有任何参数;
3、被注解的方法返回值必须为void
;
4、被注解方法不得抛出已检查异常;
5、此方法只会被执行一次;
@PostConstruct
是Java
自带的注解,在方法上添加该注解时,Spring
容器初始化的时候会执行该方法。从Java EE5
规范开始,Servlet
中存在两个注解@PostConstruct
和@PreDestroy
影响Servlet
生命周期(加载-实例化-初始化-服务-销毁),这两个注解用来修饰非静态的void
无参方法;
@PostConstruct
与@PreDestroy
区别:
【1】@PostConstruct
用于标记一个方法,在对象创建后立即执行。它通常用于执行一些初始化操作,例如初始化成员变量或建立数据库连接。
【2】@PreDestroy
用于标记一个方法,在对象销毁之前执行。它通常用于执行一些清理操作,例如关闭数据库连接或释放资源。
总结来说,@PostConstruct
用于在对象创建后执行初始化操作,而@PreDestroy
用于在对象销毁前执行清理操作。这两个注解都是由依赖注入框架自动调用的,无需手动调用。
二、代码
@Service
public class UserAutoBookProcess{// 使用到了依赖注入对象@Autowiredprivate ChineseConfig chineseConfig;private Map<Integer, String> map = null;// 初始化方法@PostConstructpublic void init(){ImmutableMap.of(1, chineseConfig.getFirst(), 2, chineseConfig.getSecord());}
}
三、源码分析
@PostConstruct
注解的实现原理是在Spring
容器初始化时,会扫描所有标有该注解的方法,并调用它们。如下:@PostConstruct
注解是一个标注在方法上的注解,用于标记一个方法是在bean
实例化后被调用的方法。它的定义比较简单,没有任何实现代码。
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}
下面我们来看一下Spring
容器是如何扫描并调用@PostConstruct
注解的方法的:Spring
容器在初始化InitDestroyAnnotationBeanPostProcessor
这个类的内部postProcessBeforeInitialization
方法里对@PostConstruct
这个注解进行识别, 然后通过反射, 对这个方法进行了调用。而postProcessBeforeInitialization
这个方法的被调是在bean
的初始化。
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata metadata = this.findLifecycleMetadata(bean.getClass());try {metadata.invokeInitMethods(bean, beanName);return bean;} catch (InvocationTargetException var5) {throw new BeanCreationException(beanName, "Invocation of init method failed", var5.getTargetException());} catch (Throwable var6) {throw new BeanCreationException(beanName, "Failed to invoke init method", var6);}
}
四、实战引用
【1】Redis
工具类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;@Component
public class RedisUtil {private static RedisTemplate<Object, Object> redisTemplates;@Autowiredprivate RedisTemplate<Object, Object> redisTemplate;@PostConstructpublic void initialize() {redisTemplates = this.redisTemplate;}/*** 添加元素** @param key* @param value*/public static void set(Object key, Object value) {if (key == null || value == null) {return;}redisTemplates.opsForValue().set(key, value);}
}