1. 程式人生 > >java 進階一:代理和動態代理

java 進階一:代理和動態代理

實現 public rgs tostring 開源項目 body llb ack code

靜態代理:

  定義頂級接口:Iservice

//目標類和代理類都實現該接口
public interface Iservice {
    public String server();
}

  定義目標類:ServiceImp 實現 Iservice接口

// 目標類
public class ServiceImp implements Iservice {
    @Override
    public String server() {
        return "hello";
    }
}

  定義代理類:ServiceProxy 實現 Iservice 接口,將目標類中目標方法的返回值變為大寫字符

// 代理類
public class ServiceProxy implements Iservice {
    
    Iservice target;
    
    public ServiceProxy() {
    }
    
    public ServiceProxy(Iservice target) {
        this.target = target;
    }

    @Override
    public String server() {
        return target.server().toUpperCase();
    }
}

測試:

public class Test {
    public static void main(String[] args) {
        Iservice target=new ServiceImp();
        Iservice proxy=new ServiceProxy(target);
        System.out.println(proxy.server());
    }
}

動態代理的兩種實現方式

  1、使用JDK的Proxy實現代理,要求目標類和代理類實現相同的接口。若目標類不存在接口,則無法使用該方式實現。

  2、對於無接口的類,需要使用CGLIB來實現代理。CGLIB代理的生成原理是生成目標類的子類,而子類是增強過的,這個子類就是代理對象。因此,使用CGLIB生成動態代理,要求目標類必須能被繼承,即不能是final修飾的類。

  CGLIB(Code Generation Library)是一個開源項目,是一個強大的、高性能的、高質量的代碼生成類庫。它可以在運行期間擴展和增強java類。Hibernate用它來實現持久對象的字節碼的動態生成,Spring用它來實現AOP編程。CGLIB包的底層是通過使用字節碼處理框架ASW(Java字節碼處理框架),來轉換字節碼並生成新的類。CGLIB是通過對字節碼進行增強來生成代理的。

相關實例代碼:

  1、Proxy實現:

public class Test {
    public static void main(String[] args) {
        // 定義目標對象
        Iservice target=new ServiceImp();
        // 定義目標對象的代理對象
        Iservice myproxy=(Iservice) Proxy.newProxyInstance(
                target.getClass().getClassLoader(), // 目標類的類加載器
                target.getClass().getInterfaces(), //目標類實現的接口
                new InvocationHandler() {
            // proxy:代理對象
            // method:目標方法
            // args:目標方法的參數
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) 
                    throws Throwable {
                Object result=method.invoke(target, args);
                if ("server".equals(method.getName())) {
                    result = result.toString().toUpperCase();
                }
                return result;
            }
            
        });
        System.out.println(myproxy.server());
    }
}

  2、CGLIB實現:

  定義目標類:Service

public class Service {
    public String server(){
        return "hello";
    }
}

  創建cglib代理:

import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor {
    private Service target;
    public CglibProxy() {
    }
    public CglibProxy(Service target){
        this.target=target;
    }
    // 創建cglib代理對象
    public Service myProxy(){
        Service service=new Service();
        Enhancer enhancer=new Enhancer();
        // 指定父類,即要增強的目標類
        enhancer.setSuperclass(Service.class);
        // 指定回調接口對象
        enhancer.setCallback(this);
        // 創建cglib代理對象
        return (Service) enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        Object result=method.invoke(target, args);
        if ("server".equals(method.getName())) {
            result = result.toString().toUpperCase();
        }
        return result;
    }
}

  測試:

public class Test {
    public static void main(String[] args) {
        // 創建目標對象
        Service target=new Service();
        // 創建目標對象的代理對象
        Service proxy=new CglibProxy(target).myProxy();
        System.out.println(proxy.server());
    }
}

java 進階一:代理和動態代理