当前位置: 首页 > news >正文

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.项目启动时

  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() {
    }
}

相关文章:

  • AcWing 蓝桥杯AB组辅导课 01、递归与递推
  • 2022软考高项十大领域知识整理(三)--项目质量管理、沟通管理
  • spring boot在线投票系统 毕业设计源码141307
  • 申请专利申请流程,专利申请详细步骤
  • echarts文档解读
  • 稀疏矩阵的压缩存储
  • 动手学习深度学习 08:机器视觉
  • CNN(卷积网络)如何处理Size(Shape)大小可变的输入图像数据
  • 小鱼的一键安装系列
  • Spring Cloud Alibaba-Ribbon的源码分析
  • MASA MAUI Plugin IOS蓝牙低功耗(三)蓝牙扫描
  • 30岁以上的程序员还死磕技术,别说拿高薪,可能连饭碗都会保不住
  • numpy快速处理数据学习笔记
  • C++多态详解
  • sqlserver sa 密码忘记 处理
  • ➹使用webpack配置多页面应用(MPA)
  • 30秒的PHP代码片段(1)数组 - Array
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • Linux链接文件
  • Puppeteer:浏览器控制器
  • python学习笔记 - ThreadLocal
  • tab.js分享及浏览器兼容性问题汇总
  • 安卓应用性能调试和优化经验分享
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 马上搞懂 GeoJSON
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 为视图添加丝滑的水波纹
  • 用jquery写贪吃蛇
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (十六)串口UART
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (转)ObjectiveC 深浅拷贝学习
  • (转)创业家杂志:UCWEB天使第一步
  • .axf 转化 .bin文件 的方法
  • .naturalWidth 和naturalHeight属性,
  • .net 获取url的方法
  • .NET分布式缓存Memcached从入门到实战
  • .NET微信公众号开发-2.0创建自定义菜单
  • .pop ----remove 删除
  • @serverendpoint注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • @Validated和@Valid校验参数区别
  • @vue/cli 3.x+引入jQuery
  • [.NET 即时通信SignalR] 认识SignalR (一)
  • [.net]官方水晶报表的使用以演示下载
  • [2]十道算法题【Java实现】
  • [20150321]索引空块的问题.txt
  • [AUTOSAR][诊断管理][ECU][$37] 请求退出传输。终止数据传输的(上传/下载)
  • [Flexbox] Using order to rearrange flexbox children
  • [GN] DP学习笔记板子
  • [Go WebSocket] 多房间的聊天室(三)自动清理无人房间