1. 程式人生 > 資訊 >滴滴正式提交赴美上市申請:全球年活躍使用者達 4.93 億

滴滴正式提交赴美上市申請:全球年活躍使用者達 4.93 億

動態代理實現

介面

public interface People {
    public int eat();
}

被代理目標

public class User implements People{
    @Override
    public int eat() {
        System.out.println("吃飯");
        return 12;
    }
}

通過實現被代理目標類的介面,並在生成的代理物件中執行需要被代理的方法,並額外新增自己需要的步驟

User user = new User();
People proxyInstance = (People) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), (proxy, method, args2) -> {
            if (method.getName().equals("eat")) {
                System.out.println("代理開啟");
                Object invoke = method.invoke(user, args2);//執行被代理方法
                System.out.println("代理關閉");
                return invoke;//返回被代理方法的返回值
            }else {
                return method.invoke(user,args2);
            }
        });

user.getClass().getClassLoader():生成代理物件使用哪個類裝載器【一般我們使用的是被代理類的裝載器】

user.getClass().getInterfaces():生成哪個物件的代理物件,通過介面指定【指定要被代理類的介面】

method:當前執行的方法

cglib代理

cglib代理也叫子類代理,從記憶體中構建出一個子類來擴充套件目標物件的功能!通過繼承被代理目標類,從而增強其中的方法
被代理目標

public class User{
    public int eat() {
        System.out.println("吃飯");
        return 12;
    }
}

```java
public class ProxyFactory implements MethodInterceptor {
    //被代理目標物件,通過構造方法傳入
    private Object target;
    public ProxyFactory(Object target){
        this.target = target;
    }

    //獲取代理物件
    public Object getProxyTarget() {
        Enhancer enhancer = new Enhancer();
        //設定代理物件的父類,也就是被代理物件
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();//建立被代理物件並返回
    }

    //代理增強方法
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("代理開啟");
        Object invoke = method.invoke(target, objects);
        System.out.println("代理關閉");
        return invoke;
    }
}

執行程式碼

User proxyTarget = (User) new ProxyFactory(user).getProxyTarget(); System.out.println(proxyTarget.eat());

靜態代理和動態代理的區別

很明顯的是:

  • 靜態代理需要自己寫代理類-->代理類需要實現與目標物件相同的介面
  • 而動態代理不需要自己編寫代理類--->(是動態生成的)

使用靜態代理時:

  • 靜態代理實現

    public class ProxyUser implements People{
        public User user = new User();
        @Override
        public int eat() {
            System.out.println("代理開啟");
            int eat = user.eat();
            System.out.println("代理關閉");
            return eat;
        }
    }
    
  • 如果目標物件的介面有很多方法的話,那我們還是得一一實現,這樣就會比較麻煩

使用動態代理時:

  • 代理物件的生成,是利用JDKAPI,動態地在記憶體中構建代理物件(需要我們指定建立 代理物件/目標物件 實現的介面的型別),並且會預設實現介面的全部方法