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)的更多相关文章

  1. Spring 拦截器实现+后台原理(HandlerInterceptor)

    过滤器跟拦截器的区别 spring mvc的拦截器是只拦截controller而不拦截jsp,html 页面文件的.这就用到过滤器filter了,filter是在servlet前执行的,你也可以理解成 ...

  2. struts2拦截器的实现原理

    拦截器(interceptor)是Struts2最强大的特性之一,也可以说是struts2的核心,拦截器可以让你在Action和result被执行之前或之后进行一些处理.同时,拦截器也可以让你将通用的 ...

  3. Spring拦截器中通过request获取到该请求对应Controller中的method对象

    背景:项目使用Spring 3.1.0.RELEASE,从dao到Controller层全部是基于注解配置.我的需求是想在自定义的Spring拦截器中通过request获取到该请求对应于Control ...

  4. spring拦截器中修改响应消息头

    问题描述 前后端分离的项目,前端使用Vue,后端使用Spring MVC. 显然,需要解决浏览器跨域访问数据限制的问题,在此使用CROS协议解决. 由于该项目我在中期加入的,主要负责集成shiro框架 ...

  5. Spring拦截器和过滤器

    什么是拦截器 拦截器(Interceptor): 用于在某个方法被访问之前进行拦截,然后在方法执行之前或之后加入某些操作,其实就是AOP的一种实现策略.它通过动态拦截Action调用的对象,允许开发者 ...

  6. struts2拦截器的实现原理及源码剖析

    拦截器(interceptor)是Struts2最强大的特性之一,也可以说是struts2的核心,拦截器可以让你在Action和result被执行之前或之后进行一些处理.同时,拦截器也可以让你将通用的 ...

  7. Spring 拦截器——HandlerInterceptor

    采用Spring拦截器的方式进行业务处理.HandlerInterceptor拦截器常见的用途有: 1.日志记录:记录请求信息的日志,以便进行信息监控.信息统计.计算PV(Page View)等. 2 ...

  8. spring 拦截器简介

    spring 拦截器简介 常见应用场景 1.日志记录:记录请求信息的日志,以便进行信息监控.信息统计.计算PV(Page View)等.2.权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直 ...

  9. Spring 拦截器实现事物

    Spring+Hibernate的实质:就是把Hibernate用到的数据源Datasource,Hibernate的SessionFactory实例,事务管理器HibernateTransactio ...

随机推荐

  1. 问题:grid卸载后重新安装时ASM磁盘识别不到了

    现象,磁盘路径是对的,但是识别不出来asmdisk2 系统显示磁盘也存在 识别不到的原因是:安装了一次磁盘已经有asm信息写入,需要擦除才能重新被识别到,命令如下 [root@swnode1 dev] ...

  2. 关于sql中in 和 exists 的效率问题

    在用in的地方可以使用freemark标签代替,例如: 将 <#if assistantList??&& (assistantList?size > 0)> AND ...

  3. Codeforces Round #425 (Div. 2) Problem A Sasha and Sticks (Codeforces 832A)

    It's one more school day now. Sasha doesn't like classes and is always bored at them. So, each day h ...

  4. 2018年11月20日 远交近攻 list1

    list 列表用法 li=[1,2,3,"abc"] #列表中的元素,可以为数字或者字符串或者布尔值或者就是列表等,所有都能放进去 #列表中也能嵌套列表 pi=[1,2,3,[2, ...

  5. topcoder srm 695 div1 -3

    1.称一个串的子串(连续一段)为$same$当且仅当这个子串所有字符都一样.子串不同当且仅当在原串中的起始位置不同.现在构造一个长度为$n$的只包含字符'a','b'的串$s$,使得$s$满足长度为$ ...

  6. Ubuntu18.04 一些好用的扩展

    原文:https://www.lulinux.com/archives/2589 一些好用的扩展: United:https://www.gnome-look.org/p/1167950/ dynam ...

  7. 【MVC】Spring MVC常用配置

    一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的jar包. 2.添加Web.xml配置文件中关于SpringMVC的配置 <!--conf ...

  8. FancyBox的使用技巧 (汇总)

    http://note.youdao.com/share/?id=1c8373249f523529a6b6dcde60777400&type=note#/

  9. git删除远程分支文件,不改变本地文件

    git提交项目时候踩的Git的坑 特别 由于准备春招,所以希望各位看客方便的话,能去github上面帮我Star一下项目 https://github.com/Draymonders/Campus-S ...

  10. 图片处理工具类 util

    PathUtil package util; public class PathUtil { private static String seperator = System.getProperty( ...