zoukankan      html  css  js  c++  java
  • spring中使用动态代理(AOP)

    spring是整合了BGLIB和JDK两种动态代理

    示例:使用CGLIB代理

    public class MyCar {
    
        private String color = "blue";
    
        public void run() {
            System.out.println("我的汽车跑起来了" + color);
        }
    }
    

    测试

    public class SpringProxy {
    
        public static void main(String[] args) {
    	   //将代理类的class文件保存到本地
            System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "E:\Java4IDEA\comm_test\com\sun\proxy");
            ProxyFactory proxyFactory = new ProxyFactory(new MyCar());
            //添加前后置通知
            addAdivce(proxyFactory);
            proxyFactory.setProxyTargetClass(true);
            MyCar proxy = (MyCar) proxyFactory.getProxy();
            proxy.run();
        }
    }
    
    

    使用JDK代理

    被代理的对象需要实现接口

    public interface Car {
        void run();
    }
    

    调用

    public static void main(String[] args) throws Exception {
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        ProxyFactory proxyFactory = new ProxyFactory(new MyCar());
        addAdivce(proxyFactory);
        //        proxyFactory.setProxyTargetClass(true);
        Car proxy = (Car) proxyFactory.getProxy();
        proxy.run();
    }
    

    如果想添加前后置通知 如下

     private static void addAdivce(ProxyFactory proxyFactory) {
            proxyFactory.addAdvice(new MethodInterceptor() {
                @Override
                public Object invoke(MethodInvocation invocation) throws Throwable {
                    Object aThis = invocation.getThis();
                    System.out.println("MethodInterceptor前置:"+aThis);
                    //执行被代理对象的方法,返回方法的返回值
                    Object proceed = invocation.proceed();
                    System.out.println("MethodInterceptor后置");
                    return proceed;
                }
            });
    
            //可以添加多个方法前置或者后置通知
            proxyFactory.addAdvice(new AfterReturningAdvice() {
                @Override
                public void afterReturning(Object returnValue, Method method,
                                           Object[] args, Object target) throws Throwable {
                    System.out.println("AfterReturningAdvice后置通知");
    
                }
            });
    
            proxyFactory.addAdvice(new MethodBeforeAdvice() {
                @Override
                public void before(Method method, Object[] args, Object target) throws Throwable {
                    System.out.println("MethodBeforeAdvice前置通知");
                }
            });
        }
    

    JDK生成的动态类

    public final class $Proxy0 extends Proxy implements Car, SpringProxy, Advised, DecoratingProxy {
        ...
        public final void run() throws  {
            try {
                super.h.invoke(this, m3, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }    
    }
    

    源码与JDK的代理和CGLB的代理源码大同小异,可以自行查阅
    也可以参考 代理模式

  • 相关阅读:
    第九章:Elasticsearch集群优化及相关节点配置说明
    Linux115条常用命令
    第一章:引擎介绍
    第七章:JAVA引用ESWCF及部分方法说明
    第八章:SCRT搭建ES搜索引擎步骤
    第三章:ES分词简单说明
    第二章:ES索引说明
    疑难杂症:Java中Scanner连续获取int和String型发生错误.
    java实现中缀表达式转后缀表达式
    编程题:输出字符集合的所有排列组合。
  • 原文地址:https://www.cnblogs.com/qiaozhuangshi/p/11185099.html
Copyright © 2011-2022 走看看