0
点赞
收藏
分享

微信扫一扫

Spring中的11个扩展点


Spring中的11个扩展点_ide

文章目录

  • ​​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容器的方式


6.项目启动时

  1. CommandLineRunner
  2. 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.初始化方法

  1. 使用@PostConstruct注解
  2. 实现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() {
}
}


举报

相关推荐

0 条评论