当前位置: 首页 > article >正文

spring中aop

jdk动态代理

Proxy.newProxyInstance(类加载器,所有的接口,代理方法InvocationHandler )

 public static void main(String[] args) {
        CalculatorImpl calculator = new CalculatorImpl();
        // 生成一个代理对象
        /**
         * 1.类加载器
         * 2. 要生成的代理对象他需要实现的接口
         * 3. InvocationHandle : 动态代理的方法
         *
         * 方法返回: 代理对象  这个对象需要实现的接、
         */
        Calculator proxObj = (Calculator) Proxy.newProxyInstance(Main.class.getClassLoader(), new Class[]{Calculator.class}, new InvocationHandler() {
            /**
             *
             * @param proxy 生成的代理对象
             *
             * @param method 被代理的方法

             *
             * @param args 方法的参数

             *
             * @return 代理方法的返回值
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                long startTime = System.currentTimeMillis();
                Object invoke = method.invoke(calculator, args);
                long endTime = System.currentTimeMillis();

                System.out.println(method.getName() + "方法执行时间" + (endTime - startTime));
                return invoke;
            }
        });


        proxObj.add(1, 2);
    }

jdk动态代理,必须要有接口

cglib动态代理

cglib本质是写一个拦截器,把当前对象的方法拦截下来,进行增强,,返回一个当前对象的子类

   <dependency>
           <groupId>cglib</groupId>
           <artifactId>cglib</artifactId>
           <version>3.3.0</version>
       </dependency>

实现MethodInterceptor接口,创建一个拦截器:

package com.cj;

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @author cc
 * @date 2025-02-20 09:25
 **/

public class MyMethodInterceptor implements MethodInterceptor {
    /**
     * 方法的拦截器,,,,将目标方法拦截下来,, 拦截下来增强功能
     * @param obj  代理的对象
     * @param method 代理的方法
     * @param args 代理的方法参数
     * @param methodProxy 被代理的方法
     * @return 代理方法的返回值
     * @throws Throwable
     */


    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        long startTime = System.currentTimeMillis();
        // 生成一个继承他的类 ,,, 调用父类的方法
        Object result = methodProxy.invokeSuper(obj, args);
        long endTime = System.currentTimeMillis();
        System.out.println("diff:"+(endTime-startTime));
        return result;
    }
}

   public static void main(String[] args) {

        
        Enhancer enhancer = new Enhancer();
        // 设置父类 ==》 根据父类生成子类
        enhancer.setSuperclass(UserService.class);

        // 设置拦截器
        enhancer.setCallback(new MyMethodInterceptor());


        // 创建代理对象
        UserService o = (UserService) enhancer.create();

        o.sayHello();
    }

生成了一个代理对象的子类,,

jdk动态代理只能代理有接口的类,,,cglib都能代理,,

spring中动态代理
 <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>6.1.14</version>
        </dependency>

ProxyFactory

 public static void main(String[] args) {
        // spring中的动态代理使用的对象
        ProxyFactory proxyFactory = new ProxyFactory();

        // 设置被代理的对象
        proxyFactory.setTarget(new CalculatorImpl());
        proxyFactory.setInterfaces(Calculator.class);

        // 设置为true,,,表示使用cglib动态代理 // 为false就会根据情况(是否有接口)自动选择
        proxyFactory.setProxyTargetClass(true);

        // 被代理方法上额外的增强逻辑
        proxyFactory.addAdvice(new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {

                Method method = invocation.getMethod();
                long startTime = System.currentTimeMillis();
                // 执行方法
                Object proceed = invocation.proceed();
                long endTime = System.currentTimeMillis();
                System.out.println("diff:"+(endTime-startTime));
                return proceed;
            }
        });


        CalculatorImpl proxy = (CalculatorImpl) proxyFactory.getProxy();
        proxy.add(1, 2);
    }
spring中aop

通知:

  • 前置通知 : 方法执行前调用
  • 后置通知
  • 返回通知 : 获取到方法返回值的时候调用
  • 异常通知: 抛出错误的时候调用
  • 环绕通知: 集大成者

写一个切面:

package com.cj;

import org.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

/**
 * 1.前置通知 :
 * 后置通知
 * 返回通知 : 拿到返回值的之后会触发,,, void也算是返回值
 * 异常通知: 抛出异常的时候触发
 * 环绕通知: 集大成者
 *
 * @author cc
 * @date 2025-02-20 10:38
 **/

public class LogAdvice {

    public void before(JoinPoint jp){
        // 目标方法的名字
        String name = jp.getSignature().getName();

        System.out.println(name+"方法开始执行了");


    }


    public void after(JoinPoint jp){
        // 目标方法的名字
        String name = jp.getSignature().getName();

        System.out.println(name+"方法执行结束了");
    }

    /**
     *
     * @param jp
     * @param val  目标方法的返回值 : 和目标方法的返回值类型一致
     */
    public void afterReturning(JoinPoint jp,Void val){
        // 目标方法的名字
        String name = jp.getSignature().getName();

        System.out.println(name+"方法afterReturning "+val);
    }


    public void afterThrowing(JoinPoint jp,Throwable e){
        String name = jp.getSignature().getName();
        System.out.println(name+"after throwing"+e.getMessage());
    }




    public Object around(ProceedingJoinPoint pjp){
        String name = pjp.getSignature().getName();

        Object proceed = null;
        try {
            System.out.println(name+"method  start");
            proceed = pjp.proceed();
            System.out.println(name+"method  end");
        } catch (Throwable e) {
            // 异常通知
            System.out.println("exception");
            throw new RuntimeException(e);
        }

        return proceed;
    }

}

xml配置:

    <bean class="com.cj.CalculatorImpl" id="calculatorImpl"/>


    <bean class="com.cj.LogAdvice" id="logAdvice" />

<!--    配置aop-->
    <aop:config>
        <aop:pointcut id="pc1" expression="execution(* com.cj.CalculatorImpl.*(..))"/>
<!--        配置切面: 把切面的bean写进去-->
        <aop:aspect ref="logAdvice">
            <aop:before method="before" pointcut-ref="pc1" />
            <aop:after method="after" pointcut-ref="pc1" />
<!--            返回的值,,, 参数一个是jp,一个是val-->
            <aop:after-returning method="afterReturning" pointcut-ref="pc1" returning="val"/>
            <aop:after-throwing method="afterThrowing" pointcut-ref="pc1" throwing="e"/>
            <aop:around method="around" pointcut-ref="pc1"/>
        </aop:aspect>
    </aop:config>
 public static void main(String[] args) {

        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        Calculator bean = ctx.getBean(Calculator.class);
        System.out.println("bean = " + bean);
        bean.add(1,2);
        bean.sub(2,1);
    }

<bean class="com.cj.CalculatorImpl" id="calculatorImpl"/> 这个实现类已经被代理了,已经取不到这个实现类的实例了,,
只能按照接口去找实现类,,,
<aop:config proxy-target-class="true"> : proxy-target-class为true表示使用cglib

java配置类使用aop
@Component
@Aspect // 标记这个类是一个切面
@EnableAspectJAutoProxy // 开启自动代理
public class LogAdvisor {


    @Pointcut("execution(* com.cj.CalculatorImpl.*(..))")
    public void pc1(){}




    @Before("pc1()")
    public void before(JoinPoint jp){
        // 目标方法的名字
        String name = jp.getSignature().getName();

        System.out.println(name+"方法开始执行了");


    }


    @After("pc1()")
    public void after(JoinPoint jp){
        // 目标方法的名字
        String name = jp.getSignature().getName();

        System.out.println(name+"方法执行结束了");
    }

    /**
     *
     * @param jp
     * @param val  目标方法的返回值 : 和目标方法的返回值类型一致
     */
    @AfterReturning(value = "pc1()",returning = "val")
    public void afterReturning(JoinPoint jp,Void val){
        // 目标方法的名字
        String name = jp.getSignature().getName();

        System.out.println(name+"方法afterReturning "+val);
    }


    @AfterThrowing(value = "pc1()",throwing = "e")
    public void afterThrowing(JoinPoint jp,Throwable e){
        String name = jp.getSignature().getName();
        System.out.println(name+"after throwing"+e.getMessage());
    }




    @Around("pc1()")
    public Object around(ProceedingJoinPoint pjp){
        String name = pjp.getSignature().getName();

        Object proceed = null;
        try {
            System.out.println(name+"method  start");
            proceed = pjp.proceed();
            System.out.println(name+"method  end");
        } catch (Throwable e) {
            // 异常通知
            System.out.println("exception");
            throw new RuntimeException(e);
        }

        return proceed;
    }
}

@EnableAspectJAutoProxy(proxyTargetClass = true) // 开启自动代理 proxyTargetClass=true 表示使用cglib动态代理


http://www.kler.cn/a/554448.html

相关文章:

  • LLC谐振变换器原理
  • 2026考研趋势深度解析:政策变化+高效工具指南
  • Spring Boot 实现 DeepSeek API 调用
  • mysql查看binlog日志
  • 云计算如何解决延迟问题?
  • OceanBase 初探学习历程之——安装部署
  • ctfshow web入门 web11-web24
  • 基于 Stanford CoreNLP 的中文自然语言处理
  • 推理优化技术
  • Python爬虫requests(详细)
  • rman 备份恢复1
  • 探索飞鹤奶粉奥秘,领会科技魅力
  • 11.编写前端内容|vscode链接Linux|html|css|js(C++)
  • 如何在 macOS 上配置 MySQL 环境变量
  • Linux sftp 使用详解
  • Qt的QToolButton的使用
  • 【Canvas】基础
  • golang panic信息捕获
  • jmeter接口测试(一)
  • 微服务入门-笔记