victory的博客

长安一片月,万户捣衣声

0%

Java | 动态代理

动态代理案例(JDK 动态代理机制)

假设我们需要通过中介租房子(告诉中介对房子的要求,由中介代我们租房子)

JDK动态代理机制和CGLIB动态代理机制的区别
1.JDK 动态代理只能代理实现了接口的类或者直接代理接口,而 CGLIB 可以代理未实现任何接口的类。 另外, CGLIB 动态代理是通过生成一个被代理类的子类来拦截被代理类的方法调用,因此不能代理声明为 final 类型的类和方法。
2.就二者的效率来说,大部分情况都是 JDK 动态代理更优秀,随着 JDK 版本的升级,这个优势更加明显。

动态代理和静态代理的区别、两种动态代理的区别
HireRoom.java(接口)

package hireroom;

public interface HireRoom {
    void hireRoom(String chaoxiang, String buju, int price);
}

HireRoomImpl.java(实现类)

package hireroom;

public class HireRoomImpl implements HireRoom{

    @Override
    public void hireRoom(String chaoxiang, String buju, int price) {
        System.out.println("我委托中介租一个朝向:" + chaoxiang + ",布局:" + buju + ",价格:" + price + "的房子");
    }

}

Agency.java(中介/代理类)

package hireroom;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class Agency implements InvocationHandler{
    private Object target;
    
    public Agency(Object target){
        this.target = target;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before");
        Object result = method.invoke(target, args);
        System.out.println("after");
        return result;
    }

}

AgencyFactory.java(中介/代理工厂)

package hireroom;

import java.lang.reflect.Proxy;

public class AgencyFactory {
    public static Object getProxy(Object target){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
                target.getClass().getInterfaces(), 
                new Agency(target));
    }
}

Main.java(测试)

package hireroom;

public class Main {
    public static void main(String[] args) {
        HireRoom hireRoom = (HireRoom) AgencyFactory.getProxy(new HireRoomImpl());
        hireRoom.hireRoom("坐南朝北", "两室一厅", 200000);
    }
}

运行结果1

再假设我们现在又有了想通过中介租车的需求,只需要再添加租车接口和实现类,然后通过上面的代理类完成租车。这也是动态代理的优点
HireCar.java(接口)

package hireroom;

public interface HireCar {
    void hireCar(String brand, int price);
}

HireCarImpl.java(实现类)

package hireroom;

public class HireCarImpl implements HireCar{

    @Override
    public void hireCar(String brand, int price) {
        System.out.println("租车:"+brand+price);
    }

}

Main.java

package hireroom;

public class Main {
    public static void main(String[] args) {
        HireRoom hireRoom = (HireRoom) AgencyFactory.getProxy(new HireRoomImpl());
        hireRoom.hireRoom("坐南朝北", "两室一厅", 200000);
        
        HireCar hireCar = (HireCar) AgencyFactory.getProxy(new HireCarImpl());
        hireCar.hireCar("宝马", 150000);
    }
}

运行结果2