• java-动态代理


    目前java动态代理的实现分为两种

    1.基于JDK的动态代理  //此代理的实现方式是利用反射,反射的用法在:https://www.cnblogs.com/hellohero55/p/11973757.html

    2.基于CGILB的动态代理

    在业务中使用动态代理,一般是为了给需要实现的方法添加预处理或者添加后续操作,但是不干预实现类的正常业务,把一些基本业务和主要的业务逻辑分离。我们一般所熟知的Spring的AOP原理就是基于动态代理实现的。

    (1)基于JDK的动态代理;需要一个接口类,一个实现类,一个代理类;测试;下面附上代码

      

    //接口类
    public interface Subject {
        
         void hello(String param);
    }
    //接口实现类
    public class SubjectImpl implements Subject{
    
        @Override
        public void hello(String param) {
            
             System.out.println("hello  " + param);
        }
    
    }
    //接口代理类
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class SubjectProxy implements InvocationHandler{
    
        private Subject subject;
        
        public SubjectProxy(Subject subject) {
            super();
            this.subject = subject;
        }
    
        @Override
        public Object invoke(Object arg0, Method method, Object[] args) throws Throwable {
             System.out.println("--------------begin-------------");
             
             //反射  invoke 方法的返回值;如果没有返回null  ; method.invoke(subject, args); 利用反射调用类里的实际方法
             Object invoke = method.invoke(subject, args);
            
             System.out.println("--------------end-------------");
             
             return invoke;
        }
    
    }
    //测试
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    
    public class SubjectMain {
        
        public static void main(String[] args) {
            
            Subject subject=new SubjectImpl();
            
            InvocationHandler subjectProxy =new SubjectProxy(subject);
             //subjectProxy.getClass().getClassLoader()代理类的加载器    subject.getClass().getInterfaces() :被代理类的接口 如果有多个,就是数组形式传入  subjectProxy:代理类实例
            Subject proxyInstance = (Subject)Proxy.newProxyInstance(subjectProxy.getClass().getClassLoader(), subject.getClass().getInterfaces(), subjectProxy);
            
            proxyInstance.hello("word");
            
        }
    }

    解析一下上面的代码,如果我们想在SubjectImpl  的方法增强一些功能 打印输出前的日志和输出后的日志,在不改源码的情况下,代理就很方便解决这个情况;先来看看再没有用代理之前的时候运行的;

        现在要在这个方法增加一个日志,在不改变源码的情况下我们就可以用刚才实现的方式了

     

     显然用了代理的方式增加了改方法

      (2)基于CGILB的动态代理:准备的工作:一个实体类,一个拦截器类,一个测试,ps :一下两个类是spring包的,并不是jdk的

           org.springframework.cglib.proxy.MethodInterceptor;

                          org.springframework.cglib.proxy.MethodProxy;      

             实现方式如下:

          

    //被代理类
    public class CGsubject {
        
         public void sayHello(String parm){
                System.out.println("hello "+parm);
            }
    }
    
    import java.lang.reflect.Method;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    public class HelloInterceptor implements  MethodInterceptor{
    
        @Override  //arg0 被代理对象的实例
        public Object intercept(Object arg0, Method methods, Object[] arg2, MethodProxy methodProxy) throws Throwable {
            
            System.out.println("begin time -----> "+ System.currentTimeMillis());
                    //methodProxy 代理方法 invokeSuper:调用拦截的方法 不要使用Invoke,会出现oom的情况  
            Object o1 = methodProxy.invokeSuper(arg0, arg2);
            
            System.out.println("end time -----> "+ System.currentTimeMillis());
            
            return o1;
     
        }
    
    
    }
    
    import org.springframework.cglib.proxy.Enhancer;
    
    public class CGmain {
        
         public static void main(String[] args) {
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(CGsubject.class);
                enhancer.setCallback(new HelloInterceptor());
                CGsubject cGsubject = (CGsubject) enhancer.create();
                cGsubject.sayHello("帅哥美女们");
            }
    }
     

        
     

  • 相关阅读:
    Nginx浅谈
    MySQL 规范
    使用nginx反向代理实现隐藏端口号
    -bash: /etc/profile: line 11: syntax error near unexpected token `$'{ ''报错问题解决
    为什么禁止在 foreach 循环里进行元素的 remove/add 操作
    Java中String字符串常量池
    前端学习路径
    Linux关闭防火墙命令
    CXF实现webService服务
    Jquery Ajax 的例子。
  • 原文地址:https://www.cnblogs.com/hellohero55/p/11976048.html
Copyright © 2020-2023  润新知