SpringBoot中Inteceptor 之 MethodInterceptor

本文详细介绍了SpringBoot中MethodInterceptor的使用,包括自定义方法拦截器、四种不同的切点构造方式,如AspectJExpressionPointcut、JdkRegexpMethodPointcut、AnnotationMatchingPointcut的实践案例,并提供了测试类进行验证。
部署运行你感兴趣的模型镜像

MethodInterceptor是AOP项目中的拦截器,它拦截的目标是方法,即使不是controller中的方法

自定义方法拦截器

package org.aopalliance.intercept;

@FunctionalInterface
public interface MethodInterceptor extends Interceptor {
    Object invoke(MethodInvocation var1) throws Throwable;
}

自定义拦截器,实现MethodInterceptor接口的invoke()方法

package com.wang.chao.micro.interceptor;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("MyMethodInterceptor  "+methodInvocation.getMethod().getName());
        return methodInvocation.proceed();
    }
}

案例一

使用aspectj execution表达定义切点;使用 AspectJExpressionPointcut定义切点并注册

package com.wang.chao.micro.interceptor.config;

import com.wang.chao.micro.interceptor.MyMethodInterceptor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class InterceptorConfig {
    public static final String traceExecution = "execution(* com.wang.chao.micro..*.*(..))";

    @Bean
    public DefaultPointcutAdvisor defaultPointcutAdvisor(){
        MyMethodInterceptor methodInterceptor = new MyMethodInterceptor();
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(traceExecution);

        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        advisor.setPointcut(pointcut);
        advisor.setAdvice(methodInterceptor);
        return advisor;
    }
}

案例二

与案例一的主要区别是用JdkRegexpMethodPointcut来构造切点

package com.wang.chao.micro.interceptor.config;

import com.wang.chao.micro.interceptor.MyMethodInterceptor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class InterceptorConfig {
    public static final String traceExecution = "execution(* com.wang.chao.micro..*.*(..))";

    @Bean
    public DefaultPointcutAdvisor defaultPointcutAdvisor() {
        MyMethodInterceptor methodInterceptor = new MyMethodInterceptor();
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        //case 1
        // AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        // pointcut.setExpression(traceExecution);

        //case 2
        JdkRegexpMethodPointcut pointcut2 = new JdkRegexpMethodPointcut();
        pointcut2.setPattern("com.wang.chao.micro.*");

        advisor.setPointcut(pointcut2);
        advisor.setAdvice(methodInterceptor);
        return advisor;
    }
}

案例三

自定义注解 AspectJExpressionPointcut 

package com.wang.chao.micro.interceptor.annotation;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InterceptorAnnotation {
}
package com.wang.chao.micro.interceptor.config;

import com.wang.chao.micro.interceptor.MyMethodInterceptor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class InterceptorConfig {
    public static final String traceAnnotationExecution = "@annotation(com.wang.chao.micro.interceptor.annotation.InterceptorAnnotation)";
    @Bean
    public DefaultPointcutAdvisor defaultPointcutAdvisor() {
        MyMethodInterceptor methodInterceptor = new MyMethodInterceptor();
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        //case 3
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(traceAnnotationExecution);

        advisor.setPointcut(pointcut);
        advisor.setAdvice(methodInterceptor);
        return advisor;
    }
}

案例四

自定义注解 AnnotationMatchingPointcut

package com.wang.chao.micro.interceptor.config;

import com.wang.chao.micro.interceptor.MyMethodInterceptor;
import com.wang.chao.micro.interceptor.annotation.InterceptorAnnotation;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class InterceptorConfig {

    @Bean
    public DefaultPointcutAdvisor defaultPointcutAdvisor() {
        MyMethodInterceptor methodInterceptor = new MyMethodInterceptor();
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        //case 4
        AnnotationMatchingPointcut pointcut = new AnnotationMatchingPointcut(null, InterceptorAnnotation.class);

        advisor.setPointcut(pointcut);
        advisor.setAdvice(methodInterceptor);
        return advisor;
    }
}

测试类

package com.wang.chao.micro.service;

import org.springframework.stereotype.Service;

@Service
public class UserService {

    public void saveUser(String name, String sex) {
        System.out.println("name = " + name + ", sex = " + sex+" id =");
        sayHello(name);
    }

    public void sayHello(String name){
        System.out.println("Hello name = " + name+" Welcome in Spring Interceptor world");
    }
}

请求调用测试 

package com.wang.chao.micro.controller;

import com.wang.chao.micro.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping(value="/" ,method = RequestMethod.GET)
    public void saveUser(String name,String sex){
       userService.saveUser(name,sex);

    }
}

启动调用测试

package com.wang.chao.micro;

import com.wang.chao.micro.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class Application {
    @Autowired
    private ApplicationContext applicationContext;
    public static void main(String[] args) {
        ApplicationContext applicationContext =  SpringApplication.run(Application.class, args);

        UserService userService=(UserService) applicationContext.getBean("userService");
        userService.saveUser("wagnchao","nan");
        userService.sayHello("wangchaochao");
    }

}

 

总结

四种构造Pointcut切点方式

AspectJExpressionPointcut   JdkRegexpMethodPointcut  AnnotationMatchingPointcut

 

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

### JDK21 中与 `MethodInterceptor` 等效的替代方案 在较新的 Java 版本中,尤其是 JDK 21, 动态代理机制已经得到了进一步的发展和完善。对于类似于 CGLIB 的 `MethodInterceptor`, 可以通过使用 Java 自带的动态代理功能来实现相同的效果。 #### 使用 `Proxy` 和 `InvocationHandler` Java 提供了一个内置的方式来进行方法拦截,即利用 `java.lang.reflect.Proxy` 类和 `java.lang.reflect.InvocationHandler` 接口。这种方式可以有效地模拟 `MethodInterceptor` 的行为: ```java import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class CustomInvocationHandler implements InvocationHandler { private final Object target; public CustomInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 方法调用前的操作 System.out.println("Before calling " + method.getName()); // 调用实际的方法并获取返回值 Object result = method.invoke(target, args); // 方法调用后的操作 System.out.println("After calling " + method.getName()); return result; } } ``` 为了创建一个代理实例,可以这样做: ```java // 假设有一个实现了某个接口的服务类 ServiceImpl Service serviceInstance = new ServiceImpl(); CustomInvocationHandler handler = new CustomInvocationHandler(serviceInstance); Service proxyInstance = (Service) Proxy.newProxyInstance( serviceInstance.getClass().getClassLoader(), new Class<?>[]{Service.class}, handler ); ``` 这种方法允许开发者定义自己的逻辑,在目标对象的方法执行之前和之后进行额外处理[^4]。 #### 使用 LambdaMetafactory 实现更高效的代理 除了传统的反射方式外,还可以考虑使用 `LambdaMetafactory` 来构建更加高效且性能更好的代理。这涉及到一些底层字节码操作的知识,但对于追求极致性能的应用场景来说是非常有价值的探索方向。 #### 关于CGLIB库的选择 尽管上述解决方案提供了原生的支持,但在某些情况下仍然可能倾向于继续使用像 CGLIB 这样的第三方库。这是因为它们通常会提供更多的灵活性以及对特定需求的支持,特别是在需要增强非接口类型的类时[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仰望星空@脚踏实地

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值