前言

废话不多说,直接进入主题。

同学们有想过这么一种情况吗: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接口介绍的更多相关文章

  1. Spring之InstantiationAwareBeanPostProcessor接口介绍

      InstantiationAwareBeanPostProcessor接口是BeanPostProcessor的子接口,通过接口字面意思翻译该接口的作用是感知Bean实例话的处理器.实际上该接口的 ...

  2. Spring事务管理接口定义

    Spring事务管理接口介绍 Spring事务管理接口: PlatformTransactionManager: (平台)事务管理器 TransactionDefinition: 事务定义信息(事务隔 ...

  3. Spring8:一些常用的Spring Bean扩展接口

    前言 Spring是一款非常强大的框架,可以说是几乎所有的企业级Java项目使用了Spring,而Bean又是Spring框架的核心. Spring框架运用了非常多的设计模式,从整体上看,它的设计严格 ...

  4. Spring中Ordered接口简介

    目录 前言 Ordered接口介绍 Ordered接口在Spring中的使用 总结 前言 Spring中提供了一个Ordered接口.Ordered接口,顾名思义,就是用来排序的. Spring是一个 ...

  5. Spring Resource框架体系介绍

    Resource介绍 在使用spring作为容器进行项目开发中会有很多的配置文件,这些配置文件都是通过Spring的Resource接口来实现加载,但是,Resource对于所有低级资源的访问都不够充 ...

  6. Spring家族主流成员介绍

    摘 要:Spring 就像一个大家族,有众多衍生产品例如 Boot,Security,JPA等等.但他们的基础都是Spring 的 IOC 和 AOP,IOC提供了依赖注入的容器,而AOP解决了面向切 ...

  7. spring boot 连接Mysql介绍

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  8. spring boot rest 接口集成 spring security(2) - JWT配置

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  9. spring boot rest 接口集成 spring security(1) - 最简配置

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

随机推荐

  1. JSON 格式介绍

    转自:http://www.json.org/json-zh.html JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写.同时也易于机器 ...

  2. cocos2d-x图层以及显示对象的基本使用

    LogoNode: #ifndef LogoNode_hpp #define LogoNode_hpp #include <stdio.h> #include "cocos2d. ...

  3. 通过java来批量生成身份证号

    通过java来批量生成身份证号,方便来测试程序. package com.diyvc.controller.user; import java.util.Calendar; import java.u ...

  4. Spring学习笔记之 Spring IOC容器(二) 之注入参数值,自动组件扫描方式,控制Bean实例化方式,使用注解方式

     本节主要内容:    1. 给MessageBean注入参数值    2. 测试Spring自动组件扫描方式    3. 如何控制ExampleBean实例化方式    4. 使用注解方式重构Jdb ...

  5. curl -x 127.0.0.1:80

    curl -x ip:80 +网址 就相当于在本地hosts文件指定一个域名,具有优先访问权.(curl -x 127.0.0.1:80这个方法适用于生产环境的服务器来测试自己做为代理商访问是否正常) ...

  6. 【MVC 4】4.MVC 基本工具(Visual Studio 的单元测试、使用Moq)

     作者:[美]Adam Freeman      来源:<精通ASP.NET MVC 4> 3.Visual Studio 的单元测试 有很多.NET单元测试包,其中很多是开源和免费的.本 ...

  7. 二分法 organ Saltless

    organ [描述] 现在某组织中(记作R)有n个人,他们的联络网形成一棵以Saltless为根的树,有边相连代表两人可以直接联络. 每个人有一个代号,Saltless代号为1,且除Saltless外 ...

  8. 前端的瑞士军刀:Modernizr.js

    前言 Modernizr.js既能给老版本浏览器打补丁,又能保证新浏览器渐进增强的用户体验. 作用: 从实际操作来看,Modernizr默认做的事情很少,除了(在你选择的情况下)给不支持html5的标 ...

  9. FZU 2148 Moon Game --判凹包

    题意:给一些点,问这些点能够构成多少个凸四边形 做法: 1.直接判凸包 2.逆向思维,判凹包,不是凹包就是凸包了 怎样的四边形才是凹四边形呢?凹四边形总有一点在三个顶点的内部,假如顶点为A,B,C,D ...

  10. 台北Unity开发者研讨会 笔记

    本文转自:http://ndark.wordpress.com/2013/05/12/20130511-台北unity开发者研讨会-笔记/ (墙外) 说明 本文单纯只是笔记,若有笔误敬请见谅. 相关参 ...