Spring 拦截器实现+后台原理(MethodInterceptor)
MethodInterceptor
MethodInterceptor是AOP项目中的拦截器(注:不是动态代理拦截器),区别与HandlerInterceptor拦截目标时请求,它拦截的目标是方法。
实现MethodInterceptor拦截器大致也分为两种:
(1)MethodInterceptor接口;
(2)利用AspectJ的注解配置;
MethodInterceptor接口:
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; public class MethodInvokeInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("before method invoke....");
Object object = methodInvocation.proceed();
System.out.println("after method invoke.....");
return object;
}
}
<!-- 拦截器 demo -->
<bean id="methodInvokeInterceptor" class="com.paic.phssp.springtest.interceptor.method.MethodInvokeInterceptor"/> <aop:config>
<!--切入点,controlller -->
<aop:pointcut id="pointcut_test" expression="execution(* com.paic.phssp.springtest.controller..*.*(..))" />
<!--在该切入点使用自定义拦截器 ,按照先后顺序执行 -->
<aop:advisor pointcut-ref="pointcut_test" advice-ref="methodInvokeInterceptor" /> </aop:config> <!-- 自动扫描使用了aspectj注解的类 -->
<aop:aspectj-autoproxy/>
执行:

AspectJ的注解
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component; @Aspect
@Component
public class AutoAspectJInterceptor { @Around("execution (* com.paic.phssp.springtest.controller..*.*(..))")
public Object around(ProceedingJoinPoint point) throws Throwable{
System.out.println("AutoAspectJInterceptor begin around......");
Object object = point.proceed();
System.out.println("AutoAspectJInterceptor end around......");
return object;
}
}
运行结果:
AutoAspectJInterceptor begin around......
>>>>:isAuthenticated=false
AutoAspectJInterceptor end around......
简单介绍下关键词:
AOP=Aspect Oriented Program 面向切面(方面/剖面)编程
Advice(通知):把各组件中公共业务逻辑抽离出来作为一个独立 的组件
Weave(织入) : 把抽离出来的组件(Advice),使用到需要使用该逻辑 地方的过程。
JoinPoint (连接点): Advice 组件可以weave的特征点。
PointCut(切入点):用来明确Advice需要织入的连接点
Aspect(切面):Aspect=Advice + PointCut
通知类型
@Before 在切点方法之前执行
@After 在切点方法之后执行
@AfterReturning 切点方法返回后执行
@AfterThrowing 切点方法抛异常执行
@Around环绕通知
执行顺序:
@Around环绕通知
@Before通知执行
@Before通知执行结束
@Around环绕通知执行结束
@After后置通知执行了!
@AfterReturning
切面设置:
可以使用&&、||、!、三种运算符来组合切点表达式
execution表达式:
"execution(public * com.xhx.springboot.controller.*.*(..))"
*只能匹配一级路径
..可以匹配多级,可以是包路径,也可以匹配多个参数
+ 只能放在类后面,表明本类及所有子类
within(类路径) 配置指定类型的类实例,同样可以使用匹配符
within(com.xhx.springboot..*)
@within(annotationType) 匹配带有指定注解的类(注:与上不同)
"@within(org.springframework.stereotype.Component)"
@annotation(annotationType) 匹配带有指定注解的方法
"@annotation(IDataSource)"
其中:IDataSource为自定义注解
import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface IDataSource {
String value() default "dataSource";
}
下面分析下Spring @Aspect :
1、注册
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator

看到实现接口BeanPostProcessor,必然在初始化Bean前后,执行接口方法。
2、解析
AspectJAutoProxyBeanDefinitionParser.java#parse()方法
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
this.extendBeanDefinition(element, parserContext);
return null;
}
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
3、具体实现
上面提到实现接口BeanPostProcessor,必然在初始化Bean前后,执行接口方法。看下面时序图:
AbstractAutoProxyCreator的postProcessAfterInitialization()方法。

DefaultAopProxyFactory.createAopProxy()方法,具体创建代理类。两种动态代理:JDK动态代理和CGLIB代理。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
} else {
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
下午有点
Spring 拦截器实现+后台原理(MethodInterceptor)的更多相关文章
- Spring 拦截器实现+后台原理(HandlerInterceptor)
过滤器跟拦截器的区别 spring mvc的拦截器是只拦截controller而不拦截jsp,html 页面文件的.这就用到过滤器filter了,filter是在servlet前执行的,你也可以理解成 ...
- struts2拦截器的实现原理
拦截器(interceptor)是Struts2最强大的特性之一,也可以说是struts2的核心,拦截器可以让你在Action和result被执行之前或之后进行一些处理.同时,拦截器也可以让你将通用的 ...
- Spring拦截器中通过request获取到该请求对应Controller中的method对象
背景:项目使用Spring 3.1.0.RELEASE,从dao到Controller层全部是基于注解配置.我的需求是想在自定义的Spring拦截器中通过request获取到该请求对应于Control ...
- spring拦截器中修改响应消息头
问题描述 前后端分离的项目,前端使用Vue,后端使用Spring MVC. 显然,需要解决浏览器跨域访问数据限制的问题,在此使用CROS协议解决. 由于该项目我在中期加入的,主要负责集成shiro框架 ...
- Spring拦截器和过滤器
什么是拦截器 拦截器(Interceptor): 用于在某个方法被访问之前进行拦截,然后在方法执行之前或之后加入某些操作,其实就是AOP的一种实现策略.它通过动态拦截Action调用的对象,允许开发者 ...
- struts2拦截器的实现原理及源码剖析
拦截器(interceptor)是Struts2最强大的特性之一,也可以说是struts2的核心,拦截器可以让你在Action和result被执行之前或之后进行一些处理.同时,拦截器也可以让你将通用的 ...
- Spring 拦截器——HandlerInterceptor
采用Spring拦截器的方式进行业务处理.HandlerInterceptor拦截器常见的用途有: 1.日志记录:记录请求信息的日志,以便进行信息监控.信息统计.计算PV(Page View)等. 2 ...
- spring 拦截器简介
spring 拦截器简介 常见应用场景 1.日志记录:记录请求信息的日志,以便进行信息监控.信息统计.计算PV(Page View)等.2.权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直 ...
- Spring 拦截器实现事物
Spring+Hibernate的实质:就是把Hibernate用到的数据源Datasource,Hibernate的SessionFactory实例,事务管理器HibernateTransactio ...
随机推荐
- RMAN入门——简介
RMAN(Recovery Manager) 1.简介 RMAN(Recovery Manager)是随Oracle服务器软件一同安装的工具软件,它可以用来备份和恢复数据库文件.归档日志和控制文件 ...
- 识别简单的答题卡(Bubble sheet multiple choice scanner and test grader using OMR, Python and OpenCV——jsxyhelu重新整编)
该博客转自www.pyimagesearch.com,进行了相关修改补充. Over the past few months I've gotten quite the number of reque ...
- 【Python31--pickle函数】
一.含义 1.pickle的实质是什么 答:利用一些算法把数据对象转换成“二进制文件”,存储在硬盘上,当然也可以放在数据库或者是另外一台计算机上 2.存放:picking,读取:unpicking 3 ...
- c和c++main函数的参数
1.代码 int main(int argc,char **argv[]) { ; } 2.分析 argc:代码参数个数 argv:二级指针,很多个字符串,这里代表参数列表 3.分析 这个代码最终被编 ...
- ChromeDriver与Chrome版本对应关系
备注: 下载ChromeDriver的时候,可以在notes.txt文件中查看版本对应关系. ----------ChromeDriver v2.29 (2017-04-04)---------- S ...
- html的进一步了解(更新中···)
(接上一次) 属性:表示事物的一些特征 属性又可分为两种: 标签属性和样式属性 两者的区别: 位置不一样 样式属性写在style中 标签属性写在标签内 写法不一样 样式属性是属性:属性值 标签属性是属 ...
- Python 数据分析 - 索引和选择数据
loc,iloc,ix三者间的区别和联系 loc .loc is primarily label based, but may also be used with a boolean array. 就 ...
- [NOI1995]石子合并 四边形不等式优化
链接 https://www.luogu.org/problemnew/show/P1880 思路 总之就是很牛逼的四边形不等式优化 复杂度\(O(n^2)\) 代码 #include <ios ...
- HDU 5852 Intersection is not allowed!(LGV定理行列式求组合数)题解
题意:有K个棋子在一个大小为N×N的棋盘.一开始,它们都在棋盘的顶端,它们起始的位置是 (1,a1),(1,a2),...,(1,ak) ,它们的目的地是 (n,b1),(n,b2),...,(n,b ...
- Sql 通过表名查找所有列名
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'ImmediacyOutKu'