SpringBoot項目開發(fā)中常用的一些技巧總結(jié)
環(huán)境:SpringBoot2.7.16
1. Bean初始化及銷毀
如你希望Bean對象被創(chuàng)建過程中執(zhí)行以下初始化動作,你可以通過實現(xiàn)InitializingBean接口或者使用@PostConstruct注解。
@Component
public class InitDataToRedis implements InitializingBean {
public void afterPropertiesSet() throws Exception {
// 初始化
}
}
@Component
public class PersonService {
@PostConstruct
public void init() {
// 初始化
}
}
如希望在容器關(guān)閉時執(zhí)行資源釋放或者其它一些動作可以實現(xiàn)DisposableBean接口或者使用@PreDestroy注解。
public class Person implements DisposableBean {
public void destroy() {
// 銷毀動作
}
}
@Component
public class PersonService {
@PreDestroy
public void destroy() {
// 銷毀
}
}
2. 單例Bean注入多例Bean
// 多例Bean
@Component
@Scope("prototype")
public class PersonService {
}
// 默認單例Bean
@Controller
public class PersonController {}
如上如何在PersonController中注入PersonService呢?通過如下方法
方法1:
@Lazy
private PersonService personService ;
方法2:
@Component
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class PersonService {}
方法3:
public class PersonController {
@Resource
private ApplicationContext context ;
public Object index() {
PersonService ps = this.context.getBean(PersonService.class) ;
}
}
3. BeanPostProcessor接口
如需要Bean在初始化前后執(zhí)行相關(guān)的動作,可以通過實現(xiàn)該接口。
public class PackBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 初始化前執(zhí)行
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// 初始化后執(zhí)行
}
}
4. BeanFactoryPostProcessor接口
如你希望在創(chuàng)建Bean對象之前修改BeanDefinition的相關(guān)屬性可以通過實現(xiàn)該接口
public PackBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition definition = beanFactory.getBeanDefinition("person") ;
// 修改了作用域
definition.setScope("prototype") ;
}
}
5. 動態(tài)注冊Bean
如需要根據(jù)添加動態(tài)注冊Bean,比如通過掃描包下的類符合條件的類注冊為Bean對象,則可以通過如下的方式。
public class RepositoryBeanDefinitionRegister implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 動態(tài)注冊person
registry.registerBeanDefinition("person", BeanDefinitionBuilder.genericBeanDefinition(Person.class).getBeanDefinition());
}
}
6.導入配置類
詳細查看《想成為Spring專家?了解@Import注解的三種用法是必備的!》
7. *Runner接口
如需要在應(yīng)用程序成功啟動以后,執(zhí)行一些任務(wù),可以通過實現(xiàn)ApplicationRunner或者CommandLineRunner接口。
public class App implements CommandLineRunner {
public void run(String... args) throws Exception {
// 執(zhí)行任務(wù)
}
}
// 或
public class App implements ApplicationRunner {
public void run(ApplicationArguments args) throws Exception {
// 執(zhí)行任務(wù)
}
}
8. 全局異常處理
當應(yīng)用發(fā)生異常時可以通過注冊全局異常處理,統(tǒng)一處理異常信息
@RestControllerAdvice
public class GlobalControllerAdvice {
@ExceptionHandler({Exception.class})
public Object handle(Exception e) {
// 其它處理
return R.failure(R.ResultCode.FAILURE, e.getMessage()) ;
}
}
10 全局類型轉(zhuǎn)換
自定義類型轉(zhuǎn)換
public class CustomGenericConverter implements GenericConverter {
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
ConvertiblePair teacherPair = new ConvertiblePair(String.class, Teacher.class) ;
ConvertiblePair studentPair = new ConvertiblePair(String.class, Student.class) ;
Set<ConvertiblePair> pairs = new HashSet<>() ;
pairs.add(teacherPair) ;
pairs.add(studentPair) ;
return pairs ;
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
String str = null ;
if (sourceType.getObjectType() == String.class) {
str = (String) source ;
}
if (targetType.getObjectType() == Teacher.class) {
String[] t = str.split("\\|") ;
return new Teacher(t[0], Integer.valueOf(t[1])) ;
}
if (targetType.getObjectType() == Student.class) {
String[] t = str.split("\\|") ;
return new Student(t[0], t[1]) ;
}
return null ;
}
}
注冊類型轉(zhuǎn)換器
@Component
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new CustomGenericConverter()) ;
}
}
以上示例注冊了一個,將字符串轉(zhuǎn)換為Teacher和Student。
11. 獲取BeanFactory對象
如果你希望在Bean中獲取BeanFactory,可以通過實現(xiàn)BeanFactoryAware接口
@Service
public class PersonService implements BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}
相關(guān)的*Aware接口,還有很多,如:ApplicationContextAware,ServletContextAware,BeanNameAware,EnvironmentAware等。
12. Web攔截器
如你需要對某些接口進行鑒權(quán)或者其它一些處理,你可以注冊自定義攔截器
@Component
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("preHandle method invoke...") ;
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("postHandle method invoke...") ;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) throws Exception {
System.out.println("afterCompletion method invoke...") ;
}
}).addPathPatterns("/**") ;
}
}
}
13. 默認AOP切面實現(xiàn)
BeanNameAutoProxyCreator
@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
beanNameAutoProxyCreator.setBeanNames("*Service") ;
beanNameAutoProxyCreator.setInterceptorNames("tokenInterceptor");
return beanNameAutoProxyCreator ;
}
上面的BeanNameAutoProxyCreator 是處理器類,只要beanName的后綴是Service結(jié)尾的都會被創(chuàng)建代理,然后通過以tokenInterceptor為beanName的攔截器增強。
以上是在SpringBoot項目開發(fā)中常用的一些技巧,希望本文對你有幫助。
完畢?。。?/p>