zoukankan      html  css  js  c++  java
  • java 代理的三种实现方式

    Java 代理模式有如下几种实现方式:

      1.静态代理。    

          2.JDK动态代理。

          3.CGLIB动态代理。

    示例,有一个打招呼的接口。分别有两个实现,说hello,和握手。代码如下。

    接口:

    public interface Greeting {
    
        public void doGreet();
    }

    实现类:

    public class SayHello implements Greeting {
    
        @Override
        public void doGreet() {
            System.out.println("Greeting by say 'hello' .");
        }
    
    }
    public class ShakeHands implements Greeting {
    
        @Override
        public void doGreet() {
            System.out.println("Greeting by shake others's hands .");
        }
    
    }
    public class KissHello  {
    
        public void doGreet() {
            System.out.println("Greeting by kiss . ");
        }
    
    }

    在不改变代码的情况下,想在执行目标方法 前后 做一些其他操作。则可以通过代理方式来实现。

    1.静态代理。需要创建代理类。代理类实现了和目标类一样的接口,代理类接收目标类对象,并在实现方法中调用目标类的实现方法前后做手脚。如下:

    public class GreetStaticProxy implements Greeting {
    
        private Greeting hello;//被代理对象
        public GreetStaticProxy(Greeting hello){
            this.hello=hello;
        }
        
        @Override
        public void doGreet() {
            before();//执行其他操作
            this.hello.doGreet();//调用目标方法
            after();//执行其他操作
        }
    
        public void before(){
            System.out.println("[StaticProxy] Come to someone.");
        }
        public void after(){
            System.out.println("[StaticProxy] Back to his own corner");
        }
    }

    测试调用:

    public class Main {
    
        public static void main(String[] args) {
            Greeting hello=new SayHello();
            Greeting shakeHands=new ShakeHands();
            
            //静态代理
            GreetStaticProxy staticHelloProxy=new GreetStaticProxy(hello);
            staticHelloProxy.doGreet();
            System.out.println();
            GreetStaticProxy shakeHandsProxy=new GreetStaticProxy(shakeHands);
            shakeHandsProxy.doGreet();
        }    
    运行结果:
    [StaticProxy] Come to someone. Greeting by say
    'hello' . [StaticProxy] Back to his own corner [StaticProxy] Come to someone. Greeting by shake others's hands . [StaticProxy] Back to his own corner

    这个方式有弊端,如果有N个接口的实现类需要被代理,则需要创建N个代理类。

    2.JDK动态代理

    创建代理类,如下:

    public class JdkProxy implements InvocationHandler {
    
        private Object target;
        
        public JdkProxy(Object obj){
            this.target=obj;
        }
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            
            Object result=null;
            before();
            result=method.invoke(target, args);
            after();
            return result;
        }
    
        
        public void before(){
            System.out.println("[JdkProxy] Come to someone.");
        }
        public void after(){
            System.out.println("[JdkProxy] Back to his own corner");
        }
    }

    测试调用:

    public class Main {
    
        public static void main(String[] args) {
            Greeting hello=new SayHello();
            Greeting shakeHands=new ShakeHands();
            
           
            //jdk动态代理
            JdkProxy dynamicProxy=new JdkProxy(hello);
            Greeting target=(Greeting) Proxy.newProxyInstance(hello.getClass().getClassLoader(),
                    hello.getClass().getInterfaces(), dynamicProxy);
            target.doGreet();
            System.out.println();          
            
        }    
        
    }

    这种方式和第一种方式相比,虽然不需要创建很多代理类,

    但是,他依赖与“被代理的对象需要实现接口” 即:在上面给出的代码示例中,动态代理可以代理SayHello和ShakeHands,却不能代理KissHello。因为KissHello没有实现接口。

    3.CGLIB动态代理。

    创建代理类:

    public class CglibProxy implements MethodInterceptor {
    
        public static CglibProxy proxy=new CglibProxy();
        private CglibProxy(){}
        
        public static CglibProxy getInstance(){
            return proxy;
        }
        
        public <T> T getProxy(Class<T> cls){
            return (T) Enhancer.create(cls, this);
        }
        
        @Override
        public Object intercept(Object obj, Method method, Object[] arg,
                MethodProxy proxy) throws Throwable {
            Object result=null;
            try {
                before();
                result= proxy.invokeSuper(obj, arg);
                after();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    
        public void before(){
            System.out.println("[cglib] Come to someone.");
        }
        public void after(){
            System.out.println("[cglib] Back to his own corner.");
        }
    }

    调用示例:

    public class Main {
    
        public static void main(String[] args) {
            
            //cglib代理
            Greeting targetProxy=CglibProxy.getInstance().getProxy(SayHello.class);
            targetProxy.doGreet();
            System.out.println();
            
            CglibProxy.getInstance().getInstance().getProxy(KissHello.class).doGreet();
            
                   
        }    
    
    }

    综上,CGLIB动态代理最好,spring框架也用到了CGLIB包。

  • 相关阅读:
    HDU 2236 无题Ⅱ
    Golden Tiger Claw(二分图)
    HDU 5969 最大的位或 (思维,贪心)
    HDU 3686 Traffic Real Time Query System (图论)
    SCOI 2016 萌萌哒
    Spring Boot支持控制台Banner定制
    构建第一个Spring Boot程序
    Spring Boot重要模块
    Java fastjson JSON和String互相转换
    BCompare 4 Windows激活方法【试用期30天重置】
  • 原文地址:https://www.cnblogs.com/demingblog/p/5276475.html
Copyright © 2011-2022 走看看