加入收藏 | 设为首页 | 会员中心 | 我要投稿 北几岛 (https://www.beijidao.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

java 代理的三种实现方式

发布时间:2021-05-21 07:23:01 所属栏目:大数据 来源: https://www.jb51.cc
导读:Java 代理模式有如下几种实现方式: 1.静态代理。 ? ? ? 2.JDK动态代理。 ? ? ? 3.CGLIB动态代理。 ? 示例,有一个打招呼的接口。分别有两个实现,说hello,和握手。代码如下。 接口: public interface Greeting { void doGreet();} 实现类: class SayHello

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

  1.静态代理。    

? ? ? 2.JDK动态代理。

? ? ? 3.CGLIB动态代理。

?

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

接口:

public interface Greeting {

    void doGreet();
}

实现类:

class SayHello implements Greeting {

    @Override
     doGreet() {
        System.out.println("Greeting by say 'hello' .");
    }

}
class ShakeHands  doGreet() {
        System.out.println("Greeting by shake others's hands ."class KissHello  {

     doGreet() {
        System.out.println("Greeting by kiss . ");
    }

}

?

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

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

class GreetStaticProxy private Greeting hello;//被代理对象
    public GreetStaticProxy(Greeting hello){
        this.hello=hello;
    }
    
    @Override
     doGreet() {
        before();//执行其他操作
        this.hello.doGreet();//调用目标方法
        after();//执行其他操作
    }

     before(){
        System.out.println("[StaticProxy] Come to someone.");
    }
     after(){
        System.out.println("[StaticProxy] Back to his own corner");
    }
}

测试调用:

 Main {

    static  main(String[] args) {
        Greeting hello=new SayHello();
        Greeting shakeHands= ShakeHands();
        
        //静态代理
        GreetStaticProxy staticHelloProxy= GreetStaticProxy(hello);
        staticHelloProxy.doGreet();
        System.out.println();
        GreetStaticProxy shakeHandsProxy= 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动态代理

创建代理类,如下:

class JdkProxy  InvocationHandler {

     Object target;
    
     JdkProxy(Object obj){
        this.target=obj;
    }
    
    @Override
     Object invoke(Object proxy,Method method,Object[] args)
            throws Throwable {
        
        Object result=null;
        before();
        result=method.invoke(target,args);
        after();
        return result;
    }

    
     before(){
        System.out.println("[JdkProxy] Come to someone." after(){
        System.out.println("[JdkProxy] Back to his own corner" ShakeHands();
        
       
        jdk动态代理
        JdkProxy dynamicProxy= 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动态代理。

创建代理类:

class CglibProxy  MethodInterceptor {

    static CglibProxy proxy= CglibProxy();
     CglibProxy(){}
    
    static CglibProxy getInstance(){
         proxy;
    }
    
    public <T> T getProxy(Class<T> cls){
        return (T) Enhancer.create(cls,);
    }
    
    @Override
     Object intercept(Object obj,Object[] arg,MethodProxy proxy)  Throwable {
        Object result=;
        try {
            before();
            result= proxy.invokeSuper(obj,arg);
            after();
        } catch (Exception e) {
            e.printStackTrace();
        }
         result;
    }

     before(){
        System.out.println("[cglib] Come to someone." after(){
        System.out.println("[cglib] Back to his own corner.");
    }
}

调用示例:

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

}

?

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

?

(编辑:北几岛)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读