「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战」。
静态代理模式
对于代理模式的理解我们可以通过生活中的一些例子来说明,比如生活中,一般自己去租房比较难,所以可以通过中介去进行代理,将其用代码模拟,就是一个简单的代理模式。
interface House{
public void Rent();
}
class Customer implements House{
@Override
public void Rent() {
System.out.println("租个房子");
}
}
class Agency implements House{
House obj;
Agency(House obj){
this.obj = obj;
}
@Override
public void Rent() {
System.out.println("我是中介");
obj.Rent();
System.out.println("租房成功!");
}
}
动态代理模式
静态代理的维护成本是比较高的,比如在House接口中新增一个方法sell,那么所有的实现了House接口的类都需要新增,这样会造成工作量比较大,所以需要使用动态代理模式\
interface House{
public void Rent();
}
interface Car{
public void drive();
}
class Customer implements House,Car{
@Override
public void Rent() {
System.out.println("租个房子");
}
@Override
public void drive() {
System.out.println("开车");
}
}
public class Main {
public static void main(String[] args) {
Car car = (Car) Proxy.newProxyInstance(Customer.class.getClassLoader(), Customer.class.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(new Customer(),args);
System.out.println(method.getName()+"被调用了");
return result;
}
});
car.drive();
}
}
通过Proxy.newProxyInstance动态生成了一个对象,这个对象没有任何的我们写的类原型,将其强制转换成Car 后可以调用Car的方法从而最终会调用invoke方法。
该过程可以理解为通过newProxyInstance方法,拿到类加载器,根据传入的接口字节码,会生成一个实现了这些接口的对象,在这个对象中的对应接口方法中会调用invoke方法。
生成的对象的模板可以理解为下面的类
class Agency implements House,Car{
//InvocationHandler是重写的匿名类对象
InvocationHandler mInvocationHandler;
Agency(InvocationHandler invocationHandler){
mInvocationHandler = invocationHandler;
}
@Override
public void Rent() {
try {
Method method = House.class.getMethod("Rent",String.class);
mInvocationHandler.invoke(this,method,new Object[]{});
}catch (Exception e){
e.printStackTrace();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
@Override
public void drive() {
try {
Method method = Car.class.getMethod("drive",String.class);
mInvocationHandler.invoke(this,method,new Object[]{});
}catch (Exception e){
e.printStackTrace();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}