SpringBoot 钩子接口的实现代码

目录
  • Aware 接口族
  • InitializingBean
  • BeanPostProcessor
  • BeanFactoryPostProcessor
  • ImportSelector
  • ImportBeanDefinitionRegistrar
  • FactoryBean
  • ApplicationListener
  • ApplicationRunner

Aware 接口族

Aware 意为感知,实现 Aware 接口并重写其方法,可以从上下文中获取当前的运行环境

常见的 aware 接口

  • BeanNameAware
  • BeanFactoryAware
  • BeanClassLoaderAware
  • ApplicationContextAware

使用

@Component
@ToString
public class TestService  implements BeanNameAware, BeanClassLoaderAware {
    private String beanName;
    private ClassLoader classLoader;

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    @Override
    public void setBeanName(String name) {
        this.beanName= name;
    }

}

InitializingBean

InitializingBean 接口用于在 Bean 的初始化阶段执行自定义的操作,类型功能的还有 DisposableBean

使用

@Component
public class TestBean implements InitializingBean, DisposableBean {

    // bean 设置完属性之后调用
    @Override
    public void afterPropertiesSet() throws Exception {
        // 初始化操作
        System.out.println("TestBean init");
    }

    // 销毁之后调用
    @Override
    public void destroy() throws Exception {
        // 释放资源
        System.out.println("TestBean destroy");
    }
}

BeanPostProcessor

BeanPostProcessor,Bean 的后置处理器,与 InitializingBean 不同的是,BeanPostProcessor 对所有 Bean 生效

使用

@Component
public class TestPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Bean 初始化前");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Bean 初始化后");
        return bean;
    }
}

BeanPostProcessor 使用场景非常多,可以获取正在初始化的 Bean 对象,然后依据该 Bean 对象做一些定制化的操作,如:判断该 Bean 是否为某个特定对象、获取 Bean 的注解元数据等

Spring 内置了非常多的 BeanPostProcessor ,以此来完善自身功能

BeanFactoryPostProcessor

BeanFactoryPostProcessor 是 Bean 工厂的后置处理器,一般用来修改上下文中的 BeanDefinition

使用

@Component
public class TestFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("所有 BeanDefinition 已被加载,但还未实例化 Bean");

        // 动态添加 BeanDefinition
        //转换为子类 DefaultListableBeanFactory
        DefaultListableBeanFactory defaultBeanFactory =
            (DefaultListableBeanFactory) beanFactory;
        //new 一个 beanDefinition对象
        GenericBeanDefinition b = new GenericBeanDefinition();
        b.setBeanClass(Testbean.class);
        //添加一个 beanDefinition 对象
        defaultBeanFactory.registerBeanDefinition("testBean", b);

        // 动态获取 BeanDefinition
  Object o = defaultBeanFactory.getBean("testBean")
    }
}

BeanDefinition 包含了 Spring 实例化一个 Bean 的所需的信息

ImportSelector

ImportSelector 可以动态的返回需要被容器管理的类,一般用来返回外部的配置类

public class TestImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {

        // AnnotationMetadata 存储注解元数据信息
        // 可以动态的返回需要被容器管理的类名称
        if (importingClassMetadata.hasAnnotation("")) {
            // 判断是否包含某个注解
        }

        // TestBean 加入到 Spring 容器中
        return new String[]{"com.example.pojo.TestBean"};
    }
}

在标注 @Configuration 注解的类中,通过 @Import 导入 ImportSelector 来使之生效

@Configuration
@Import(TestImportSelector.class)
public class TestConfig {
}

ImportBeanDefinitionRegistrar

ImportBeanDefinitionRegistrar 也是配合 @Import 使用,可直接将 Bean 注册到容器中

使用

public class TestRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
                                        BeanDefinitionRegistry registry) {
        GenericBeanDefinition b = new GenericBeanDefinition();
        b.setBeanClass(NotScanBean.class);
        b.setLazyInit(true);
        // 注册到容器中
        registry.registerBeanDefinition(NotScanBean.class.getName(), b);
    }
}

FactoryBean

FactoryBean 为创建 Bean 提供了更加灵活的方式,常用于用于创建一类 Bean

Bean 实现 FactoryBean 后,通过 getBean(String BeanName) 获取到的 Bean 对象并不是 FactoryBean 的实现类对象,而是这个实现类中的 getObject() 方法返回的对象,在 BeanName 之前加上 &,可以获取 FactoryBean 的实现类对象

使用

@Component
public class TestFactoryBean implements FactoryBean<TestBean> {
    @Override
    public TestBean getObject() throws Exception {

        // 对 Bean 进行配置
        // 如代理、修饰等

        return new TestBean();
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }
}

ApplicationListener

ApplicationListener 是 Spring 实现事件机制的核心接口,属于观察者设计模式

ApplicationContext 可以发布 ApplicationEvent 事件,之后所有的 ApplicationListener 会被回调

自定义 ApplicationEvent

public class TestApplicationEvent extends ApplicationEvent {

    public TestApplicationEvent(Object source) {
        super(source);
    }

    public void hello(){
        System.out.println("Hello Word!");
    }
}

自定义 ApplicationListener

@Component
public class TestApplicationListener implements ApplicationListener {

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof TestApplicationEvent) {
            TestApplicationEvent testApplicationEvent = (TestApplicationEvent) event;
            testApplicationEvent.hello();
        }
    }
}

通过注入 ApplicationContext 或实现 ApplicationContextAware 接口,获取 ApplicationContext 对象,发布 ApplicationEvent

@SpringBootTest
class DemoApplicationTests {

    @Autowired
    ApplicationContext applicationContext;

    @Test
    public void test() {
        applicationContext.publishEvent(new TestApplicationEvent(new DemoApplication()));
    }
}
// Hello Word!

ApplicationRunner

SpringBoot 应用启动成功会 callRunners 方法,所有 ApplicationRunner 实现类都会被回调

实现 AppilcationRunner,ApplicationArguments 类型用来接收启动参数

@Component
public class MyApplicationRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("原始参数:" + Arrays.asList(args.getSourceArgs()));
        Set<String> keys = args.getOptionNames();
        for (String key : keys) {
            System.out.println("解析后的 key: [" + key + "]  value: " + args.getOptionValues(key));
        }
        System.out.println("无 OptionName 的参数: " + args.getNonOptionArgs());
    }
}
// 例:启动参数 --a=1 --b c
// 打印 =>
// 原始参数:[--a=1, --b, c]
// 解析后的 key: [a]  value: [1]
// 解析后的 key: [b]  value: []
// 无 OptionName 的参数: [c]

CommandLineRunner 和 ApplicationRunner 类似,但是只能获得没有经过解析的原始参数

到此这篇关于SpringBoot 钩子接口的实现代码的文章就介绍到这了,更多相关SpringBoot 钩子接口内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot整合Swagger3生成接口文档过程解析

    前后端分离的项目,接口文档的存在十分重要.与手动编写接口文档不同,swagger是一个自动生成接口文档的工具,在需求不断变更的环境下,手动编写文档的效率实在太低.与新版的swagger3相比swagger2配置更少,使用更加方便. 一.pom文件中引入Swagger3依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId

  • SpringBoot设置接口超时时间的方法

    SpringBoot设置接口访问超时时间有两种方式 一.在配置文件application.properties中加了spring.mvc.async.request-timeout=20000,意思是设置超时时间为20000ms即20s, 二.还有一种就是在config配置类中加入: public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void configureAsyncSupport(fin

  • 浅谈spring-boot 允许接口跨域并实现拦截(CORS)

    本文介绍了spring-boot 允许接口跨域并实现拦截(CORS),分享给大家,也给自己留个笔记 pom.xml(依赖的jar) // 在spring-boot-starter-web的启动器中,已经依赖好了 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependen

  • Spring Boot实现通用的接口参数校验

    本文介绍基于 Spring Boot 和 JDK8 编写一个 AOP ,结合自定义注解实现通用的接口参数校验. 缘由 目前参数校验常用的方法是在实体类上添加注解,但对于不同的方法,所应用的校验规则也是不一样的,例如有一个 AccountVO 实体: public class AccountVO { private String name; // 姓名 private Integer age; // 年龄 } 假设存在这样一个业务:用户注册时需要填写姓名和年龄,用户登陆时只需要填写姓名就可以了.那

  • SpringBoot后端接口的实现(看这一篇就够了)

    摘要:本文演示如何构建起一个优秀的后端接口体系,体系构建好了自然就有了规范,同时再构建新的后端接口也会十分轻松. 一个后端接口大致分为四个部分组成:接口地址(url).接口请求方式(get.post等).请求数据(request).响应数据(response).如何构建这几个部分每个公司要求都不同,没有什么"一定是最好的"标准,但一个优秀的后端接口和一个糟糕的后端接口对比起来差异还是蛮大的,其中最重要的关键点就是看是否规范! 本文就一步一步演示如何构建起一个优秀的后端接口体系,体系构建

  • 解决Vue调用springboot接口403跨域问题

    最近在做一个前后端分离的项目, 前端用的是Vue后端使用的是springboot, 在项目整合的时候发现前端调用后端接口报错403跨域请求问题 前端跨域请求已解决, 那么问题就出在后端了, 找了一些资料找到了很多种方法, 这里说两个简单粗暴的. 注意:"@CrossOrigin"注解要求jdk1.8及以上版本, SpringMVC 4.2及以上版本 1. 在controller层上添加@Configuration注解, 如果没有效果请制定RequestMapping总的method类型

  • 详解Spring Boot实战之Filter实现使用JWT进行接口认证

    本文介绍了spring Boot实战之Filter实现使用JWT进行接口认证,分享给大家 jwt(json web token) 用户发送按照约定,向服务端发送 Header.Payload 和 Signature,并包含认证信息(密码),验证通过后服务端返回一个token,之后用户使用该token作为登录凭证,适合于移动端和api jwt使用流程 本文示例接上面几篇文章中的代码进行编写,请阅读本文的同时可以参考前面几篇文章 1.添加依赖库jjwt,本文中构造jwt及解析jwt都使用了jjwt库

  • SpringBoot项目访问任意接口出现401错误的解决方案

    之前搭建了一个SpringBoot项目用于测试集成Redis和MyBatis以及Freemarker,搭建完成测通之后就没有再打开过.今天打开之后想要测试一个问题,发现在这个项目下无论请求哪个接口,浏览器都会跳转到一个登录页面,而且这个页面不是我写的,如下图: 地址栏里的login也是在我输入了自己的接口之后,自动跳转到了login 于是用Postman测试,得到401响应: 当时一脸蒙蔽,心想我代码里面没有写拦截器啊,而且拦截之后的页面也不是我写的.刚开始认为可能和端口有关,后来发现不是.于是

  • SpringBoot接口加密解密统一处理

    我们与客户端的接口交互中,为了更高的安全性,我们可能需要对接口加密(请求参数加密,服务端解密).返回信息加密(服务端加密,客户端解密),但是也不是所有的接口都这样,有些接口可能不需要,我们可以使用注解来轻松达到此要求. 将接口参数的加密解密和返回信息的加密解密分开,分别定义注解,利用Controller的ControllerAdvice来拦截所有的请求,在其中判断是否需要加密解密,即可达到要求. 使用方法:使用 DecryptRequest 和 EncryptResponse 注解即可,可以放在

  • SpringBoot 钩子接口的实现代码

    目录 Aware 接口族 InitializingBean BeanPostProcessor BeanFactoryPostProcessor ImportSelector ImportBeanDefinitionRegistrar FactoryBean ApplicationListener ApplicationRunner Aware 接口族 Aware 意为感知,实现 Aware 接口并重写其方法,可以从上下文中获取当前的运行环境 常见的 aware 接口 BeanNameAware

  • Vue+Springboot实现接口签名的示例代码

    1.实现思路 接口签名目的是为了,确保请求参数不会被篡改,请求的数据是否已超时,数据是否重复提交等. 接口签名示意图 客户端提交请求时,将以下参数按照约定签名方式进行签名,随后将参数和签名一同提交服务端: 1.请求头部分(header) appid:针对不同的调用方分配不同的appid. noce:请求的流水号,防止重复提交. timestamp:请求时间戳,验证请求是否已超时失效. 2.数据部分 Path:按照path中的参数将所有key=value进行拼接. Query:按照所有key=va

  • SpringBoot实现接口等幂次校验的示例代码

    目录 主流的实现方案如下: 第一步:书写redis工具类 第二步.书写token工具类 第三步:定义注解,使用在方法上,当控制层的方法上被注释时,表示该请求为等幂性请求 第四步:拦截器配置.选择前置拦截器,每次请求都校验到达的方法上是否有等幂性注解,如果有则进行token校验 第五步:对拦截器进行url模式匹配,并注入spring容器 第六步:控制层 接口等幂性通俗的来说就是同一时间内,发起多次请求只有一次请求成功:其目的时防止多次提交,数据重复入库,表单验证网络延迟重复提交等问题. 比如: 订

  • Spring钩子接口汇总分析使用示例

    目录 1.Aware 系列接口 2.InitializingBean 3.BeanPostProcessor 4.BeanFactoryPostProcessor 5.FactoryBean 6.ApplicationListener 1.Aware 系列接口 Aware 系列接口是用来获取 Spring 内部对象的接口.Aware 自身是一个顶级接口,它有一系列子接口,在一个 Bean 中实现这些子接口并重写里面的 set 方法后,Spring 容器启动时,就会回调该 set 方法,而相应的对

  • SpringBoot集成swagger的实例代码

    Swagger 是一款RESTFUL接口的文档在线自动生成+功能测试功能软件.本文简单介绍了在项目中集成swagger的方法和一些常见问题.如果想深入分析项目源码,了解更多内容,见参考资料. Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步.Swagger 让部署管理和使用功能强大的API从未如此简单. 对于

  • SpringBoot集成JPA的示例代码

    本文介绍了SpringBoot集成JPA的示例代码,分享给大家,具体如下: 1.创建新的maven项目 2. 添加必须的依赖 <!--springboot的必须依赖--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE

  • springboot使用dubbo和zookeeper代码实例

    这篇文章主要介绍了springboot使用dubbo和zookeeper代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 创建服务接口模块 接口工程只提供接口,不提供实现,在后面的提供者和消费者中使用 在使用接口的模块中只需要写具体实现类,避免了在每个模块中重复编写接口 在接口中引入依赖包 <dependency> <groupId>org.projectlombok</groupId> <artifact

  • springboot使用事物注解方式代码实例

    这篇文章主要介绍了springboot使用事物注解方式代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考 1.在启动类Application中添加注解@EnableTransactionManagement import tk.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springfra

  • SpringBoot实现接口数据的加解密功能

    一.加密方案介绍 对接口的加密解密操作主要有下面两种方式: 自定义消息转换器 优势:仅需实现接口,配置简单. 劣势:仅能对同一类型的MediaType进行加解密操作,不灵活. 使用spring提供的接口RequestBodyAdvice和ResponseBodyAdvice 优势:可以按照请求的Referrer.Header或url进行判断,按照特定需要进行加密解密. 比如在一个项目升级的时候,新开发功能的接口需要加解密,老功能模块走之前的逻辑不加密,这时候就只能选择上面的第二种方式了,下面主要

  • springboot跨域CORS处理代码解析

    这篇文章主要介绍了springboot跨域CORS处理代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一 源(Origin) 源指URL的协议,域名,端口三部分组成,如果这个三个成分都相同,就判定是同源,否则为不同源. 同源策略(Same origin policy)是一种浏览器的约定,即在浏览器中禁止非同源访问. 二 CORS CORS即"跨域资源共享"(Cross-origin resource sharing),是一个W

随机推荐