代理模式

(一)什么是代理模式
通过引入一个代理对象,来操作、控制、访问真实对象。
给目标对象提供一个代理,并由代理对象控制对目标对象的引用。
(二)静态代理
1)模式结构
这里写图片描述

2)角色
Subject: 抽象主题角色
RealSubject: 真实主题角色
Proxy: 代理主题角色
3)简化的结构图
代理模式示意结构图比较简单,一般可以简化为如下图所示,但是在现实中要复杂很多。
这里写图片描述
4)代码示例:

//接口
public interface IUserDao {
    void save();
}
//目标对象;真实对象;要被代理的对象
public class UserDao implements IUserDao {

    @Override
    public void save() {
        System.out.println("-----数据已经保存了-----");
    }

}
//代理对象,静态代理
public class Proxy implements IUserDao {
    //把目标对象作为代理类的属性
    private IUserDao target;

    //采用聚合的方式,把目标对象通过构造参数传过来
    public Proxy(IUserDao target) {
        super();
        this.target = target;
    }

    @Override
    public void save() {
        System.out.println("开始事务...");
        target.save();
        System.out.println("提交事务...");
    }

}
//客户端测试
public class MyTest {
    public static void main(String[] args) {
        //目标对象
        IUserDao target=new UserDao();

        //把目标对象通过构造参数传给代理对象
        Proxy proxy=new Proxy(target);

        proxy.save();
    }
}

(三)JDK动态代理
1)代码示例

//接口
public interface UserService {
    void add();
}
//目标对象;被代理对象;需要实现接口
public class UserServiceImpl implements UserService {

    @Override
    public void add() {
        System.out.println("添加数据");
    }

}
//把目标对象传给这个类,并通过这个类的getProxy方法拿到目标对象的代理对象
public class ProxyFactory {

    //维护一个目标对象
    private Object target;
    public ProxyFactory(Object target) {
        super();
        this.target = target;
    }

    //创建一个InvocationHandler对象
    private InvocationHandler handler=new InvocationHandler() {
        @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;
        }
    };

    //为目标对象创建代理对象
    public Object getProxy(){
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(), 
                target.getClass().getInterfaces(), 
                handler);
    }
}
//客户端测试类
public class MyTest {
    public static void main(String[] args) {
        //目标对象
        UserService service=new UserServiceImpl();

        //获取代理对象
        //该代理对象一定会实现目标对象的接口UserService,因此可以强转
        UserService proxy=(UserService)new ProxyFactory(service).getProxy();
        proxy.add();
    }
}

注意:在JDK动态代理中,目标对象一定要实现接口,否则不能使用JDK动态代理
(四)cglib动态代理
思考:上面的静态代理和JDK动态代理,都要求目标对象实现某个接口。如果目标对象没有实现任何接口,那该怎么办呢?这时候应该使用cglib动态代理。
1)cglib动态代理,为指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
2)需要引入cglib的jar包,由于Spring的核心包中已经包括了cglib功能,所以直接引入spring-core-4.0.6.RELEASE.jar即可。
3)代码示例

//目标对象,未实现任何接口
public class UserDao {  
    public void print(){
        System.out.println("hello world");
    }
}
//把目标对象传给这个类,并且通过这个类获取目标对象的代理对象
public class Cglib implements MethodInterceptor{
    //维护目标对象
    private Object target;
    public Cglib(Object target) {
        super();
        this.target = target;
    }

    //为目标对象创建代理对象
    public Object getProxy(){
        //工具类
        Enhancer en=new Enhancer();
        //设置父类
        en.setSuperclass(target.getClass());
        //设置回调函数
        en.setCallback(this);
        //创建代理对象
        return en.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("开始事务...");
        Object result=method.invoke(target, args);
        System.out.println("提交事务...");
        return result;
    }   
}
//客户端测试类
public class MyTest {
    public static void main(String[] args) {
        //目标对象
        UserDao dao=new UserDao();

        //获取代理对象
        //代理类是目标类UserDao的子类,因此可以强转
        UserDao proxy=(UserDao)new Cglib(dao).getProxy();
        proxy.print();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值