Spring中的11个扩展点
文章目录
- 1.自定义拦截器
- 2.获取Spring容器对象
- 2.1 BeanFactoryAware接口
- 2.2 ApplicationContextAware接口
- 2.3 ApplicationListener接口
- 3.全局异常处理
- 4.类型转换器
- 5.Bean放入Spring容器的方式
- 6.项目启动时
- 7.修改BeanDefinition
- 8.初始化Bean前后
- 9.初始化方法
- 9.1 使用@PostConstruct注解
- 9.2 实现InitializingBean接口
- 10.关闭容器前
- 11.自定义作用域
1.自定义拦截器
spring mvc拦截器根spring拦截器相比,它里面能够获取HttpServletRequest和HttpServletResponse等web对象实例。
spring mvc拦截器的顶层接口是:HandlerInterceptor,包含三个方法:
- preHandle 目标方法执行前执行
- postHandle 目标方法执行后执行
- afterCompletion 请求完成时执行
为了方便我们一般情况会用HandlerInterceptor接口的实现类HandlerInterceptorAdapter类。
假如有权限认证、日志、统计的场景,可以使用该拦截器。
public class AuthInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String requestUrl = request.getRequestURI();
if (checkAuth(requestUrl)) {
return true;
}
return false;
}
private boolean checkAuth(String requestUrl) {
System.out.println("===权限校验===");
return true;
}
}
拦截器注册到spring容器
@Configuration
public class WebAuthConfig extends WebMvcConfigurerAdapter {
@Bean
public AuthInterceptor getAuthInterceptor() {
return new AuthInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor());
}
}
2.获取Spring容器对象
2.1 BeanFactoryAware接口
@Service
public class PersonService implements BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public void add() {
Person person = (Person) beanFactory.getBean("person");
}
}
实现BeanFactoryAware接口,然后重写setBeanFactory方法,就能从该方法中获取到spring容器对象。
2.2 ApplicationContextAware接口
@Service
public class PersonService2 implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public void add() {
Person person = (Person) applicationContext.getBean("person");
}
}
实现ApplicationContextAware接口,然后重写setApplicationContext方法,也能从该方法中获取到spring容器对象。
2.3 ApplicationListener接口
@Service
public class PersonService3 implements ApplicationListener<ContextRefreshedEvent> {
private ApplicationContext applicationContext;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
applicationContext = event.getApplicationContext();
}
public void add() {
Person person = (Person) applicationContext.getBean("person");
}
}
3.全局异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public String handleException(Exception e) {
if (e instanceof ArithmeticException) {
return "数据异常";
}
if (e instanceof Exception) {
return "服务器内部异常";
}
retur nnull;
}
}
4.类型转换器
spring目前支持3中类型转换器:
- Converter<S,T>:将 S 类型对象转为 T 类型对象
- ConverterFactory<S, R>:将 S 类型对象转为 R 类型及子类对象
- GenericConverter:它支持多个source和目标类型的转化,同时还提供了source和目标类型的上下文,这个上下文能让你实现基于属性上的注解或信息来进行类型转换。
5.Bean放入Spring容器的方式
链接: https://blog.csdn.net/qq_43141726/article/details/127235432?spm=1001.2014.3001.5501
6.项目启动时
- CommandLineRunner
- ApplicationRunner
@Component
public class TestRunner implements ApplicationRunner {
@Autowired
private LoadDataService loadDataService;
public void run(ApplicationArguments args) throws Exception {
loadDataService.load();
}
}
实现自己定制化需求
7.修改BeanDefinition
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
beanDefinitionBuilder.addPropertyValue("id", 123);
beanDefinitionBuilder.addPropertyValue("name", "959ggg");
defaultListableBeanFactory.registerBeanDefinition("user", beanDefinitionBuilder.getBeanDefinition());
}
}
在postProcessBeanFactory方法中,可以获取BeanDefinition的相关对象,并且修改该对象的属性。
8.初始化Bean前后
BeanPostProcessor接口:
- postProcessBeforeInitialization 该在初始化方法之前调用。
- postProcessAfterInitialization 该方法再初始化方法之后调用。
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof User) {
((User) bean).setUserName("959ggg");
}
return bean;
}
}
9.初始化方法
- 使用@PostConstruct注解
- 实现InitializingBean接口
9.1 使用@PostConstruct注解
@Service
public class AService {
@PostConstruct
public void init() {
System.out.println("===初始化===");
}
}
9.2 实现InitializingBean接口
@Service
public class BService implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("===初始化===");
}
}
10.关闭容器前
关闭资源
@Service
public class DService implements InitializingBean, DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean afterPropertiesSet");
}
}
通常情况下,我们会同时实现InitializingBean和DisposableBean接口,重写初始化方法和销毁方法。
11.自定义作用域
我们都知道spring默认支持的Scope只有两种:
- singleton 单例,每次从spring容器中获取到的bean都是同一个对象。
- prototype 多例,每次从spring容器中获取到的bean都是不同的对象。
spring web又对Scope进行了扩展,增加了:
- RequestScope 同一次请求从spring容器中获取到的bean都是同一个对象。
- SessionScope 同一个会话从spring容器中获取到的bean都是同一个对象。
同一个线程中从spring容器获取到的bean都是同一个对象:
public class ThreadLocalScope implements Scope {
private static final ThreadLocal THREAD_LOCAL_SCOPE = new ThreadLocal();
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
Object value = THREAD_LOCAL_SCOPE.get();
if (value != null) {
return value;
}
Object object = objectFactory.getObject();
THREAD_LOCAL_SCOPE.set(object);
return object;
}
@Override
public Object remove(String name) {
THREAD_LOCAL_SCOPE.remove();
return null;
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
}
@Override
public Object resolveContextualObject(String key) {
return null;
}
@Override
public String getConversationId() {
return null;
}
}
第二步将新定义的Scope注入到spring容器中:
@Component
public class ThreadLocalBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
beanFactory.registerScope("threadLocalScope", new ThreadLocalScope());
}
}
第三步使用新定义的Scope:
@Scope("threadLocalScope")
@Service
public class CService {
public void add() {
}
}