参考:https://blog.csdn.net/catoop/article/details/71274561
一、@PostConstruct注解的使用(会在这个bean类依赖注入初始化之后执行,一般为该bean初始化一些属性资源):
- 该类中只有一个方法可以使用此注释进行注解;
- 被注解方法不得有任何参数;
- 被注解方法返回值为void;
- 被注解方法不得抛出已检查异常;
- 被注解方法需是非静态方法;
- 此方法只会被执行一次;
- spring中Constructor、@Autowired、@PostConstruct的顺序:Constructor >> @Autowired >> @PostConstruct,@PostConstruct注解的方法将会在依赖注入完成后被自动调用。
二、实现SmartLifecycle接口(在Spring加载和初始化所有bean后被调用(start()方法),一般用来执行启动服务:监听、开启线程池、为某个属性进行bean赋值等等、添加ShutdownHook等等),建议每个spring项目都配置一个实现该接口的类。
例子:
package com.xiaomi.cashpay.userrights.construct;
import com.xiaomi.cashpay.userrights.service.UserPrivacyObtainIntf;
import com.xiaomi.cashpay.userrights.service.impl.CreditCardPrivacyObtainService;
import com.xiaomi.cashpay.userrights.service.impl.UserPrivacyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.SmartLifecycle;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import java.util.Map;
import javax.annotation.Resource;
/**
* @description:
* @author: wangpeng
* @create: 2018-07-11 18:08
**/
@Component
public class ProjectSmartLifecycle implements SmartLifecycle {
private static final Logger logger = LoggerFactory.getLogger(ProjectSmartLifecycle.class);
private boolean isRunning = false;
@Resource
private ThreadPoolTaskExecutor userPrivacyDataObtainThreadPool;
/**
* 根据该方法的返回值决定是否执行start方法。<br/> 返回true时start方法会被自动执行,返回false则不会。
*/
@Override
public boolean isAutoStartup() {
return true;
}
/**
* 1. 我们主要在该方法中启动任务或者其他异步服务,比如开启MQ接收消息等等<br/> 2. 当上下文被刷新(所有对象已被实例化和初始化之后)时,将调用该方法,默认生命周期处理器将检查每个SmartLifecycle对象的isAutoStartup()方法返回的布尔值。
* 如果为“true”,则该start()方法会被调用,而不是等待显式调用自己的start()方法。
*/
@Override
public void start() {
// 执行完其他业务后,可以修改 isRunning = true
isRunning = true;
logger.info("cashpay-user-rights-web项目starting");
// add 用户隐私的实现类(即UserPrivacyObtainIntf接口的实现类)
addUserPrivacyObtainService();
//添加shutdown处理钩子
addShutdownHook();
logger.info("cashpay-user-rights-web项目started");
}
/**
* 如果工程中有多个实现接口SmartLifecycle的类,则这些类的start的执行顺序按getPhase方法返回值从小到大执行。<br/> 例如:1比2先执行,-1比0先执行。
* stop方法的执行顺序则相反,getPhase返回值较大类的stop方法先被调用,小的后被调用。
*/
@Override
public int getPhase() {
// 默认为0
return 0;
}
/**
* 1. 只有该方法返回false时,start方法才会被执行。<br/> 2. 只有该方法返回true时,stop(Runnable callback)或stop()方法才会被执行。
*/
@Override
public boolean isRunning() {
// 默认返回false
return isRunning;
}
/**
* SmartLifecycle子类的才有的方法,当isRunning方法返回true时,该方法才会被调用。
*/
@Override
public void stop(Runnable callback) {
// 如果你让isRunning()返回true,需要执行stop这个方法,那么就不要忘记调用callback.run()。
// 否则在你程序退出时,Spring的DefaultLifecycleProcessor会认为你这个TestSmartLifecycle没有stop完成,程序会一直卡着结束不了,等待一定时间(默认超时时间30秒)后才会自动结束。
// PS:如果你想修改这个默认超时时间,可以按下面思路做,当然下面代码是springmvc配置文件形式的参考,在SpringBoot中自然不是配置xml来完成,这里只是提供一种思路。
// <bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
// <!-- timeout value in milliseconds -->
// <property name="timeoutPerShutdownPhase" value="10000"/>
// </bean>
callback.run();
isRunning = false;
}
/**
* 接口Lifecycle的子类的方法,只有非SmartLifecycle的子类才会执行该方法。<br/> 1. 该方法只对直接实现接口Lifecycle的类才起作用,对实现SmartLifecycle接口的类无效。<br/>
* 2. 方法stop()和方法stop(Runnable callback)的区别只在于,后者是SmartLifecycle子类的专属。
*/
@Override
public void stop() {
isRunning = false;
}
/**
* @return void
* @description /add 用户隐私的实现类(即UserPrivacyObtainIntf接口的实现类)
* @author wangpeng
* @date 2018/7/11 18:31
*/
private void addUserPrivacyObtainService() {
Map<String, UserPrivacyObtainIntf> userPrivacyObtainServiceMap =
SpringBeanFactory.getBeansOfType(UserPrivacyObtainIntf.class);
for (Map.Entry<String, UserPrivacyObtainIntf> entry : userPrivacyObtainServiceMap.entrySet()) {
UserPrivacyObtainIntf userPrivacyObtainService = entry.getValue();
if (userPrivacyObtainService instanceof CreditCardPrivacyObtainService) {
UserPrivacyService.USER_PRIVACY_OBTAIN_SERVICE_LIST.add(userPrivacyObtainService);
}
}
}
/**
* @return void
* @description 添加JVM关闭的钩子,用于做一些处理
* @author wangpeng
* @date 2018/5/23 14:41
*/
private void addShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
logger.info("cashpay-user-rights-web项目closing");
// 关闭线程池(内部调用的是shutdownNow(),会中断运行的线程)
userPrivacyDataObtainThreadPool.shutdown();
logger.info("cashpay-user-rights-web项目closed");
}
}));
}
}