代理模式

Proxy模式

静态代理模式

静态代理模式的两种实现,一种根据接口,一种根据继承

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o407Yoxk-1615292000019)(C:\Users\10374\AppData\Roaming\Typora\typora-user-images\image-20210309153754607.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zSwT4JUv-1615292000029)(C:\Users\10374\AppData\Roaming\Typora\typora-user-images\image-20210309153803895.png)]

public interface OrderInterface {
     String Order(String FoodName);
}
public class Customer implements OrderInterface {
    @Override
    public String Order(String FoodName) {
         return "点单了" + FoodName;
    }
}
public class DeliveryClerk implements OrderInterface{
    private OrderInterface source;

    public DeliveryClerk(OrderInterface source) {
        this.source = source;
    }

    @Override
    public String Order(String FoodName) {
        String result=source.Order(FoodName);
        System.out.println("已经接受了点单");
        System.out.println("已经取餐");
        return result+"搅拌均匀";
    }
}

缺点:维护复杂,父类或者接口发生变动,代理类的代码就会随之改动

动态代理

在运行期中,在内存中,jvm造出一个代理类对象供我们使用。

基于jdk的动态代理

要求被代理对象,也就是目标类,必须实现接口

Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.
Proxy.newProxyInstance throws IllegalArgumentException for the same reasons that Proxy.getProxyClass does.
Params:
loader – the class loader to define the proxy class
interfaces – the list of interfaces for the proxy class to implement
h – the invocation handler to dispatch method invocations to
Returns:
a proxy instance with the specified invocation handler of a proxy class that is defined by the specified class loader and that implements the specified interfaces
Throws:
IllegalArgumentException – if any of the restrictions on the parameters that may be passed to getProxyClass are violated
SecurityException – if a security manager, s, is present and any of the following conditions is met:
the given loader is null and the caller’s class loader is not null and the invocation of s.checkPermission with RuntimePermission(“getClassLoader”) permission denies access;
for each proxy interface, intf, the caller’s class loader is not the same as or an ancestor of the class loader for intf and invocation of s.checkPackageAccess() denies access to intf;
any of the given proxy interfaces is non-public and the caller class is not in the same runtime package as the non-public interface and the invocation of s.checkPermission with ReflectPermission(“newProxyInPackage.{package name}”) permission denies access.
NullPointerException – if the interfaces array argument or any of its elements are null, or if the invocation handler, h, is null

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)

通过该方法生成实例,loader表示定义代理的类加载器,interfaces表示实现的类,h表示调用分派到的调用处理程序

Invokes the underlying method represented by this Method object, on the specified object with the specified parameters. Individual parameters are automatically unwrapped to match primitive formal parameters, and both primitive and reference parameters are subject to method invocation conversions as necessary.
If the underlying method is static, then the specified obj argument is ignored. It may be null.
If the number of formal parameters required by the underlying method is 0, the supplied args array may be of length 0 or null.
If the underlying method is an instance method, it is invoked using dynamic method lookup as documented in The Java Language Specification, Second Edition, section 15.12.4.4; in particular, overriding based on the runtime type of the target object will occur.
If the underlying method is static, the class that declared the method is initialized if it has not already been initialized.
If the method completes normally, the value it returns is returned to the caller of invoke; if the value has a primitive type, it is first appropriately wrapped in an object. However, if the value has the type of an array of a primitive type, the elements of the array are not wrapped in objects; in other words, an array of primitive type is returned. If the underlying method return type is void, the invocation returns null.
Params:
obj – the object the underlying method is invoked from
args – the arguments used for the method call
Returns:
the result of dispatching the method represented by this object on obj with parameters args
Throws:
IllegalAccessException – if this Method object is enforcing Java language access control and the underlying method is inaccessible.
IllegalArgumentException – if the method is an instance method and the specified object argument is not an instance of the class or interface declaring the underlying method (or of a subclass or implementor thereof); if the number of actual and formal parameters differ; if an unwrapping conversion for primitive arguments fails; or if, after possible unwrapping, a parameter value cannot be converted to the corresponding formal parameter type by a method invocation conversion.
InvocationTargetException – if the underlying method throws an exception.
NullPointerException – if the specified object is null and the method is an instance method.
ExceptionInInitializerError – if the initialization provoked by this method fails.

public Object invoke(Object obj, Object... args)   

该方法表示调用method对象表示的方法,obj表示调用的方法,args表示参数

public class Customer implements OrderInterface {
    @Override
    public String Order(String FoodName) {
         return "点单了" + FoodName;
    }
}
public interface OrderInterface {
     String Order(String FoodName);
}
public class test {
    @Test
    public static void main(String[] args) {
        Customer customer = new Customer();
        OrderInterface deliveryClerk = (OrderInterface) Proxy.newProxyInstance(
                customer.getClass().getClassLoader(),
                customer.getClass().getInterfaces(),
                (proxy, method, args1) -> {
                    if ("Order".equals(method.getName())) {
                        Object invoke = method.invoke(customer, args1);
                        System.out.println("已经接受了点单");
                        System.out.println("已经取餐");
                        return invoke + "搅拌均匀";
                    } else {
                        return method.invoke(customer, args1);
                    }
                });
        String result = deliveryClerk.Order("麻婆豆腐");
        System.out.println(result);
    }
}

底层就是通过Java的反射进行调用

public class DeliveryClerk implements OrderInterface {
    //接受外部传递过来的InvocationHandler对象
    private final InvocationHandler handler;

    public DeliveryClerk(InvocationHandler handler) {
        this.handler = handler;
    }

    @Override
    public String Order(String FoodName) {
        try {
            Method method = OrderInterface.class.getMethod("Order", String.class);
            Object result = handler.invoke(this, method, new Object[]{FoodName});
            return (String) result;
        }catch (Throwable throwable){
            throwable.printStackTrace();
        }
        return null;
    }
}

基于CGLib的动态代理

不要求目标类实现接口,但要求目标类不能是最终类,也就是不能被final修饰。

public class Customer implements OrderInterface {
    @Override
    public String Order(String FoodName) {
         return "点单了" + FoodName;
    }
}
public class DynamicTest {
    @Test
    public static void main(String[] args) {
        Customer customer = new Customer();
        Customer deliveryClerk = (Customer) Enhancer.create(customer.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                if ("Order".equals(method.getName())) {
                    Object result = method.invoke(customer, args);
                    return result + ",额外添加佐料";
                } else {
                    return method.invoke(customer, args);
                }
            }
        });
        String result = deliveryClerk.Order("鱼香肉丝");
        System.out.println(result);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值