Proxy代理模式

Proxy Pattern(即:代理模式),23种常用的面向对象软件的设计模式之一
代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
优点:

  • 真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
  • 代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了的作用和保护了目标对象的作用。
  • 高扩展性

一个是真正的你要访问的对象(目标类),另一个是代理对象,真正对象与代理
对象实现同一个接口,先访问代理类再访问真正要访问的对象。


代理模式的要求:
  1. 代理这和被代理这实现相同的接口
  2. 代理者必须有被代理这的实例(引用)
  3. 代理这调用被代理这的方法

静态代理:简单代理
代理者和被代理这需要是实现共同的接口,即我们的装饰模式
创建一个潘金莲对象,实现Kindweman接口,同时创建一个代理者王婆也实现这个接口


public class PJL implements  KindWeman{
    @Override
    public void ShowEyes(Double money) {
        System.out.println("PJL 拿到"+money+"元钱,showeyes");

    }
    @Override
    public void DoSe(Double money) {
        System.out.println("PJL 拿到"+money+"元钱,Dose");
    }
}

public class WP implements KindWeman {
    private KindWeman kw = null;


    public WP(KindWeman kw ){
        this.kw = kw;
    }
    @Override
    public void ShowEyes(Double money) {
        kw.ShowEyes(money);
    }

    @Override
    public void DoSe(Double money) {
        kw.DoSe(money);
    }
}

潘金莲需要王婆的代理,代理者调用的方法都是被代理者的

public static void main(String[] args){
        KindWeman KW = new PJL();
        WP p = new WP(KW);

        p.ShowEyes(3.0);
        p.DoSe(6.0);
    }

动态代理
动态代理它可以直接给某一个目标对象生成一个代理对象,而不需要代理类存在。
动态代理与代理模式原理是一样的,只是它没有具体的代理类,直接通过反射生成了一个代理对象。
动态代理生成技术:
1、jdk提供一个Proxy类可以直接给实现接口类的对象直接生成代理对象。
2、cglib (spring框架)

Java.lang.reflect.Proxy类可以直接生成一个代理对象,看例子,这里不需要王婆这个代理者,jdk给我们提供了。

 @Test
public void test(){
    KindWeman kw = new PJL();
    //创建一个代理对象
    //ClassLoader:类加载器。固定写法,和被代理类使用相同的类加载器即可。kw.getClass().getClassLoader()
    //Class[] interface:代理类要实现的接口。固定写法,和被代理类使用相同的接口即可。kw.getClass().getInterfaces()
    //InvocationHandler:策略(方案)设计模式的应用。如何代理?即代理的过程,你需要的操作
    KindWeman KWproxy = (KindWeman) 
    Proxy.newProxyInstance(kw.getClass().getClassLoader(), kw.getClass().getInterfaces(), new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //nvocationHandler中的invoke方法:调用代理类的任何方法,此方法都会执行 
            //Object proxy:代理对象本身的引用。一般用不着。
            //Method method:当前调用的方法。通过反射, KWproxy调用誰,这里的Method就是谁
            //Object[] args:当前方法用到的参数
            System.out.println("我是中间代理:需要收取费用");
            Object o = method.invoke(kw, new Object[]{(Double) args[0] / 2});
            System.out.println("事务完成,下次再来!");
            return o;
        }
    });
    KWproxy.ShowEyes(6.0);
    KWproxy.ShowEyes(3.0);
}

这里写图片描述
使用这个思想,在我们前面讲到的业务层调用ThreadLocal管理,就不必要在servce层面上编写了。编写一个类来动态的获取服务,然后在代理当中添加ThreadLocal类实现事务的功能

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

import com.itheima.service.AccountService;
import com.itheima.service.impl.AccountServiceImpl;

public class ObjectFactory {
    //方法返回一个代理对象
    public static AccountService getAccountService(){
        final AccountService  as= new AccountServiceImpl(); 


        AccountService proxy = (AccountService) Proxy.newProxyInstance(as.getClass().getClassLoader(), as.getClass().getInterfaces(), new InvocationHandler() {

            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                Object invoke = null;
                try {

                    ManagerThreadLocal.startTransacation();//begin
                    //执行的是真实对象的转账方法
                    invoke = method.invoke(as, args);

                    ManagerThreadLocal.commit();//提交事务
                } catch (Exception e) {
                    try {
                        ManagerThreadLocal.rollback();//回滚事务
                    } catch (Exception e1) {
                        e1.printStackTrace();
                    } 
                }finally{
                    try {
                        ManagerThreadLocal.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }//关闭
                }
                return invoke;
            }
        });
        return proxy;   
    }
}
public void transfer(String fromname, String toname, double money) throws Exception {
    //  ad.updateAccount(fromname, toname, money);
        AccountDao ad = new AccountDaoImpl();


            //分别得到转出和转入账户对象
            Account fromAccount = ad.findAccountByName(fromname);
            Account toAccount = ad.findAccountByName(toname);

            //修改账户各自的金额
            fromAccount.setMoney(fromAccount.getMoney()-money);
            toAccount.setMoney(toAccount.getMoney()+money);

            //完成转账操作
            ad.updateAccout(fromAccount);
        int i = 10/0;
            ad.updateAccout(toAccount);


    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值