设计模式之代理模式 Java版

代理模式的参与者:

  1. 目标对象
  2. 代理对象
    通过代理模式来增强对象的:增强参数列表 、返回值类型 、方法体
    例如添加日志系统,验证功能,这也是面向切面编程的思想。

代理模式的实现方式:

静态代理:

简单说就是重定义一个类来增强目标对象

package com.proxy;

public class StaticProxy {
    public static void main(String[] args) {
        //1. 目标对象
        BuyCar buyCar = new BuyCar();

        //2. 代理对象
        BuyProxy buyProxy = new BuyProxy(buyCar);

        //3. 调用代理对象方法
        buyProxy.buy("car");
    }
}

//目标对象的接口
interface BuySome {
    String buy(String name);
}

/**
 * 目标对象
 */
class BuyCar implements BuySome {

    @Override
    public String buy(String name) {
        System.out.println("buy " + name);
        return "ok";
    }
}

/**
 * 代理对象
 */
class BuyProxy implements BuySome {
    //接收目标对象
    private BuySome buySome;
    public BuyProxy( final BuySome buySome){
        this.buySome = buySome;
    }
    @Override
    public String buy(String name) {
        System.out.println("付钱");
        return buySome.buy(name);

    }
}
  • 静态代理总结:
    优点:可以做到在符合开闭原则的情况下对目标对象进行功能扩展。
    缺点:我们为每一个目标对象,都得书写一个代理对象
    在上述代码中: 对于BuyCar类,我们需要写一个BuyProxy类来进行代理
    这样整个过程 存在一个接口,两个实现类
动态代理:在内存中代理形成代理类
1. 代理对象和真实对象有相同的接口
2. 代理对象 使用 Proxy.newInstance()来动态创建
package com.proxy;

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

public class ProxyTest {

    public static void main(String[] args) {
        Customer customer = new Customer();
        /**
         * 参数
         * 1. 真实对象 class
         * 2. 真实对象 interface
         * 3. new InvocationHandler() 处理器
         */
        ProxyCustomer proxy = (ProxyCustomer)Proxy.newProxyInstance(customer.getClass().getClassLoader(),
                customer.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    /**
                     *  1. proxy 代理(目标)对象
                     *  2. method 代理(目标)对象封装的方法类
                     *  3. args 代理对象调用方法时的参数
                     */
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						// 目标对象的buy方法
                        if(method.getName().equals("buy")){
                            //1. 增强参数 对参数进行处理之类的操作
                            //double money = (double) args[0];
                            //增强方法 在业务逻辑中加入 日志,验证过程等
                            System.out.println("付钱过程");
                            //使用真实对象调用方法
                            Object object = method.invoke(customer, args);
                            //增强返回值 对返回值进行封装等操作
                            return object.toString();
                        } else{
                            return null;
                        }
                    }
                });
        System.out.println(proxy.buy(" 汽车 "));
    }
}
//目标对象
class Customer implements ProxyCustomer{
    public String buy(String name){
        System.out.println("购买 " + name);
        return "ds";
    }
}
//目标对象的接口
interface ProxyCustomer{
    String buy(String name);
}   
  • 动态代理总结:
  • 优点:动态生成代理对象,脱离了对代理对象的依赖,动态代理大大减少了我们的开发任务,同时减少了对业务接口的依赖,降低了耦合度
    在代码中我们值建立了一个接口,一个对象比静态代理少了一个类
  • 缺点:Jdk动态代理仅支持interface代理的,不能用于没有父接口的类
CGLIB代理:实现对class的动态代理
  • 原理:CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑,但因为采用的是继承,所以不能对final修饰的类进行代理。
package com.proxy;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * CGLIB动态代理
 */
public class CglibProxy {
    public static void main(String[] args) {
        //1. 目标对象
        BuyHouse buyHouse = new BuyHouse();
        //2. 代理对象
        CProxy cglibProxy = new CProxy();
        BuyHouse buyHouseCglibProxy = (BuyHouse) cglibProxy.getInstance(buyHouse);
        //3. 代理方法调用
        buyHouseCglibProxy.buy("房子");
    }
}

// CGLIB工具类,将创建过程封装了
class CProxy{
    //目标对象
    private Object target;

    public Object getInstance(final Object target) {
        this.target = target;
        //创建Enhancer对象,类似于JDK动态代理的Proxy类,下一步就是设置几个参数
        Enhancer enhancer = new Enhancer();
        //获取目标对象的类型 字节码文件
        enhancer.setSuperclass(this.target.getClass());
        //设置回调方法,在这方法里面调用目标对象的方法
        enhancer.setCallback(new MethodInterceptor(){
            @Override
            public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                //参数增强 对参数args进行增强
            	
                //方法增强 增加业务逻辑
                System.out.println("买前准备");
                Object result = proxy.invokeSuper(object, args);
				// 返回值进行增强 
                return result;
            }
        });
        //正式创建代理类
        return enhancer.create();
    }
}
/**
 * 目标对象 没有接口的
 */
class BuyHouse {
    public String buy(String name) {
        System.out.println("buy " + name);
        return "ok";
    }
}

JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值