对代理模式的解读和实现

什么是代理模式

代理:自己不做,找人帮你做。
代理模式:在一个原有功能的基础上添加新的功能。
分类:静态代理和动态代理。

在这里插入图片描述

静态代理

代理类由程序员自己编写(代理类会对目标对象的特定方法进行增强)

基本步骤

1、设计接口:代理对象和目标对象都实现同一个功能。
2、编写目标对象(类):实现接口
3、编写代理对象(类):实现接口,注入目标对象,调用其方法,最后增强方法。

实现

原有方式:核心业务和服务方法都编写在一起

public class TeamService {
    public void add(){
        try {
            System.out.println("开始事务");
            System.out.println("TeamService---- add----");// 核心业务
            System.out.println("提交事务");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("回滚事务");
        }
    }
}

代理方式实现:

/**
* 切面:服务代码,切入到核心代码中,切入到哪里,给了四个位置
*/
public interface AOP {
    void before();
    void after();
    void exception();
    void myFinally();
}
public class TranAOP implements AOP {
    @Override
    public void before() {
        System.out.println("事务----before");
    }
    @Override
    public void after() {
        System.out.println("事务----after");
    }
    @Override
    public void exception() {
        System.out.println("事务----exception");
    }
    @Override
    public void myFinally() {
        System.out.println("事务----myFinally");
    }
}
public class LogAop implements AOP{
    @Override
    public void before() {
        System.out.println("日志----before");
    }
    @Override
    public void after() {
        System.out.println("日志----after");
    }
    @Override
    public void exception() {
        System.out.println("日志----exception");
    }
    @Override
    public void myFinally() {
        System.out.println("日志----myFinally");
    }
}
public class ProxyAOPService implements IService {
    private IService service;//被代理对象
    private AOP aop;//要加入切面
    public ProxyAOPService(IService service, AOP aop) {
        this.service = service;
        this.aop = aop;
    }
    @Override
    public void add() {
    try {
        aop.before();
        service.add();//被代理对象干活
        aop.after();
    }catch (Exception e){
        aop.exception();
    }finally {
        aop.myFinally();
        }
    }
}
@Test
public void test02(){
    IService teamService=new TeamService();//被代理对象--核心内容
    AOP logAop=new LogAop();//切面-服务内容
    AOP tranAop=new TranAOP();
    IService service=new ProxyAOPService(teamService,logAop); //代理对象--一级代理
    IService service2=new ProxyAOPService(service,tranAop);//代理对象--二级代理
    service2.add();
}

总结

1)可以做到在不修改目标对象的功能前提下,对目标对象功能扩展。
2)缺点:
因为代理对象,需要与目标对象实现一样的接口。所以会有很多代理类,类太多。
一旦接口增加方法,目标对象与代理对象都要维护。

每次编写一个目标类的时候,都需要重新去编写(至少)一个代理类,太麻烦了,因此我们希望系统可以自动生成代理对象,即动态代理。

动态代理

静态代理:要求代理类一定存在,
动态代理:程序运行的时候,根据要被代理的对象动态生成代理类。
类型: 
1、基于JDK的动态代理
2、基于CGLIB的动态代理

基于JDK的动态代理

public class ProxyFactory {
    private IService service;//目标对象
    private AOP aop;//切面
    public ProxyFactory(IService service, AOP aop) {
        this.service = service;
        this.aop = aop;
    }
   /**
    * 获取动态代理的示例
    * @return
    */
    public Object getProxyInstance() {
        return Proxy.newProxyInstance(
            service.getClass().getClassLoader(),
            service.getClass().getInterfaces(),
            new InvocationHandler() {//回调函数 编写代理规则
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    try {
                    aop.before();
                    Object invoke = method.invoke(service, args);//核心业务
                    aop.after();
                    return invoke;
                    }catch (Exception e){
                        aop.exception();
                        e.printStackTrace();
                        throw e;
                    }finally {
                        aop.myFinally();
                    }
                }
            }
        );
    }
}
public static void main(String[] args) {
        //目标对象--被代理对象
        TeamService teamService=new TeamService();
        //切面
        AOP tranAop=new TranAOP();
        AOP logAop=new LogAop();
        //获取代理对象
        IService service= (IService) new ProxyFactory(teamService,tranAop).getProxyInstance();
        IService service1= (IService) new ProxyFactory(service,logAop).getProxyInstance();
        service1.add();//核心业务+服务代码混合在一起的完整的业务方法
}

代理对象不需要实现接口,但是目标对象一定要实现接口;否则不能用JDK动态代理
如果想要功能扩展,但目标对象没有实现接口,怎样功能扩展?
子类的方式实现代理CGLIB。

基于CGLIB的动态代理

Cglib代理,也叫做子类代理。在内存中构建一个子类对象从而实现对目标对象功能的扩展。

  • JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用CGLIB实现。
  • CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception。
  • CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
核心方法功能
Enhancer:核心类,提供目标对象的子类对象(代理对象)
create():提供代理对象
MethodInterceptor:接口
intercept:抽象方法,对目标对象方法的增强
public class CglibProxyFactory {
    //目标对象
    private NBAService nbaService;//没有实现接口的
    //切面
    private AOP aop;//切面
   /**
    * 创建代理对象
    * @param nbaService
    * @param aop
    * @return
    */
    public Object getProxyInstance(NBAService nbaService,AOP aop){
        return Enhancer.create(nbaService.getClass(),
            new MethodInterceptor() {
                @Override
                public Object intercept(Object o, Method method, Object[]
objects, MethodProxy methodProxy) throws Throwable {
                         try {
                             aop.before();
                             Object o1 = methodProxy.invokeSuper(o, objects);
                             aop.after();
                             return o1;
                         }catch (Exception e){
                             aop.exception();
                             throw e;
                         } finally {
                             System.out.println("finally-----------");
                         }
                     }
                 });
        }
    }
public static void main(String[] args) {
    //目标对象:没有接口
    NBAService nbaService=new NBAService();
    //创建切面
    AOP tranAop=new TranAOP();
    //创建代理对象:选择cglib动态代理
    NBAService proxyInstance = (NBAService) new CglibProxyFactory().getProxyInstance(nbaService, tranAop);
    int res=proxyInstance.add("huren",1001);
    System.out.println(res);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值