Spring的BeanPostProcesser接口介绍
前言
废话不多说,直接进入主题。
同学们有想过这么一种情况吗:Spring容器提供给我们的一些接口实现类并不能满足我们的要求,但是我们又不想重新写一个类,只想在原来类上修改一些属性?
举个例子,SpringMVC中通过<mvc:annotation-driven>标签自动生成的RequestMappingHandlerAdapter有个HandlerMethodArgumentResolverComposite类型的argumentResolvers属性,这个属性内部有个HandlerMethodArgumentResolver集合属性,最终会使用这个集合处理Controller中参数的问题。这部分的知识请参考:详解SpringMVC中Controller的方法中参数的工作原理
我们通过源码来看下这个属性的初始化过程:

然后处理参数的时候会遍历HandlerMethodArgumentResolver集合属性,这样自定义的HandlerMethodArgumentResolver的优先级就落后了。
如果我们想让自定义的HandlerMethodArgumentResolver在优先级提高,怎么办呢? 可以使用BeanPostProcessor接口实现。
Spring官方文档对BeanPostProcessor接口的定义:Factory hook that allows for custom modification of new bean instances, e.g. checking for marker interfaces or wrapping them with proxies. 简单翻译下:一个工厂钩子,允许对工厂中的bean实例进行自定义修改,比如标记接口或使用代理类包装bean。
实例讲解
首先看下BeanPostProcessor接口的定义:
public interface BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
接口很简单,2个方法。 看名字也知道,初始化之前的操作和初始化之后的操作。
参数bean代表工厂中的实例;beanName代表这个实例的名字;返回值代表最终使用的beanName这个名字的实例,可以用个包装类,也可以用原先的那个bean。
这里的实例就是我们要修改RequestMappingHandlerAdapter中argumentResolvers属性里的HandlerMethodArgumentResolver集合顺序。
BeanPostProcessor的实现类代码:
@Component
public class HandlerAdapterPostProcessor implements BeanPostProcessor{
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//初始化之前不改变,原bean返回
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof RequestMappingHandlerAdapter && beanName.equals("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#0")) {
RequestMappingHandlerAdapter adapter = (RequestMappingHandlerAdapter) bean;
List<HandlerMethodArgumentResolver> resolvers = adapter.getArgumentResolvers();
//这里的resolvers是一个UnmodifiableList,因此需要重新new一个其他类型的List
List<HandlerMethodArgumentResolver> newList = new ArrayList(resolvers);
newList.add(0, new FormObjArgumentResolver());
adapter.setArgumentResolvers(Collections.unmodifiableList(newList));
}
return bean;
}
}
这里我们判断RequestMappingHandlerAdapter的时候根据beanName为org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#0的进行判断。
这里简单说明一下这个beanName的问题,为什么我们写成这样: 楼主的配置文件中定义了1个RequestMappingHandlerAdapter(没有写id属性),又写了<mvc:annotation-driven/>这句配置,且自定义的配置顺序在<mvc:annotation-driven/>之前。 这样就产生了2个RequestMappingHandlerAdapter,name分别为org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#0和org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#1。
当然可以给自定义的RequestMappingHandlerAdapter配置id属性,这样自定义的RequestMappingHandlerAdapter的beanName为配置的id属性,而<mvc:annotation-driven/>配置的RequestMappingHandlerAdapter的beanName为org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#0。参考资料:Spring中Ordered接口简介
注意,我们加了@Component注解,在配置文件中需要配置component-scan扫描到这个类,Spring容器会自动查询实现了BeanPostProcessor接口的实现类并执行该接口定义的方法。
我们这里仅仅在第一个位置加入了FormObjArgumentResolver这个自定义的实现HandlerMethodArgumentResolver接口的类。
结果:

总结
在这里再次感叹Spring框架的强大,Spring预留给我们实现的接口太多了。 很多地方只需要实现某些接口,就会默认Spring的默认行为,而无需修改源码。 赞!
Spring的BeanPostProcesser接口介绍的更多相关文章
- Spring之InstantiationAwareBeanPostProcessor接口介绍
InstantiationAwareBeanPostProcessor接口是BeanPostProcessor的子接口,通过接口字面意思翻译该接口的作用是感知Bean实例话的处理器.实际上该接口的 ...
- Spring事务管理接口定义
Spring事务管理接口介绍 Spring事务管理接口: PlatformTransactionManager: (平台)事务管理器 TransactionDefinition: 事务定义信息(事务隔 ...
- Spring8:一些常用的Spring Bean扩展接口
前言 Spring是一款非常强大的框架,可以说是几乎所有的企业级Java项目使用了Spring,而Bean又是Spring框架的核心. Spring框架运用了非常多的设计模式,从整体上看,它的设计严格 ...
- Spring中Ordered接口简介
目录 前言 Ordered接口介绍 Ordered接口在Spring中的使用 总结 前言 Spring中提供了一个Ordered接口.Ordered接口,顾名思义,就是用来排序的. Spring是一个 ...
- Spring Resource框架体系介绍
Resource介绍 在使用spring作为容器进行项目开发中会有很多的配置文件,这些配置文件都是通过Spring的Resource接口来实现加载,但是,Resource对于所有低级资源的访问都不够充 ...
- Spring家族主流成员介绍
摘 要:Spring 就像一个大家族,有众多衍生产品例如 Boot,Security,JPA等等.但他们的基础都是Spring 的 IOC 和 AOP,IOC提供了依赖注入的容器,而AOP解决了面向切 ...
- spring boot 连接Mysql介绍
Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...
- spring boot rest 接口集成 spring security(2) - JWT配置
Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...
- spring boot rest 接口集成 spring security(1) - 最简配置
Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...
随机推荐
- SQLServer中char与varchar的区别
今天写一个项目的用户登录部分 刚开始做,所以是数据库和程序一起写 一开始没注意 在定义表T_Person时吧PerID和PerPwd的类型设定都是char(20) 并且写入了几个数据,诸如 id:01 ...
- PS网页设计教程XXVIII——如何在PS中创建一个干净的网页布局
作为编码者,美工基础是偏弱的.我们可以参考一些成熟的网页PS教程,提高自身的设计能力.套用一句话,“熟读唐诗三百首,不会作诗也会吟”. 本系列的教程来源于网上的PS教程,都是国外的,全英文的.本人尝试 ...
- 《SQL Server企业级平台管理实践》读书笔记——当我们的备份都已经损坏的时候该怎么办
作为数据库管理员最最痛苦的莫过于,当数据库宕机的时候需要找备份,但在这个时候突然发现备份文件也是坏的,这就意味着数据会丢失,为此可能会丢掉职位,饭碗不保,所以为此,我们一定要保证好备份的完整性,一般发 ...
- Ubuntu15.04装机配置脚本
#!/bin/bash echo "vim" sudo apt-get install vim cp -r ./vim/.vim ~/ cp ./vim/.vimrc ~/ ech ...
- Merge Two Sorted Lists
Merge Two Sorted Lists https://leetcode.com/problems/merge-two-sorted-lists/ Merge two sorted linked ...
- Linux内核阅读相关
一.likely()与unlikely()函数的意义 http://blog.chinaunix.net/uid-27665626-id-3506567.html 二.TSO.UFO.GSO.LRO. ...
- Astyle编程语言格式化工具的中文说明
Artistic Style 1.23Maintained by: Jim PatteeOriginal Author: Tal Davidson Usage : astyle [options] ...
- hadooop 配置多网卡 提供跨网段服务
http://hortonworks.com/blog/multihoming-on-hadoop-yarn-clusters/ https://hadoop.apache.org/docs/r2.6 ...
- 使用flume的一个例子
新项目中需要使用到hadoop和vertica,使用flume把数据加载到hadoop中,我做了一个例子, 即监控一个sharefolder,如果里面有文件,则会文件load到hadoop. 开启Fl ...
- 【jQuery Demo】jQuery打造动态下滑菜单
作者:漫凯维奇 来源:[教程]jQuery打造动态下滑菜单 Tip:这只是一个转载,源代码可以在上面的来源博文中下载 此教程将分步讲解如何使用JQuery和CSS打造一个炫酷动感菜单.效果如 ...