【Spring】代理模式--动态代理

代理模式-- 动态代理

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

1 基于JDK的动态代理

【Spring】代理模式--动态代理
静态的,直接用Proxy.调用
newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
    ClassLoader :类加载器,因为动态代理类,借助别人的类加载器。一般使用被代理对象的
类加载器。
    Class[] interfaces:接口类对象的集合,针对接口的代理,针对哪个接口做代理,一般使用的
就是被代理对象的接口。
InvocationHandler:句柄,回调函数,编写代理的规则代码

public Object invoke(Object arg0, Method arg1, Object[] arg2)
    Object arg0:代理对象
    Method arg1:被代理的方法
    Object[] arg2:被代理方法被执行的时候的参数的数组

public class MyJDKProxy { 
public static void main(String[] args) { 
    //目标对象--被代理对象 
    TeamService teamService=new TeamService(); 
    //返回代理对象 
    //调用JDK中Proxy类中的静态方法newProxyInstance获取动态代理类的实例 
    IService proxyService= (IService) Proxy.newProxyInstance( 
        teamService.getClass().getClassLoader(), 
        teamService.getClass().getInterfaces(), 
        new InvocationHandler() {
            //回调函数 编写代理规则 
            @Override 
            public Object invoke(Object proxy, Method method, Object[] 
                args) throws Throwable { 
                try { 
                    System.out.println("开始事务"); 
                    //核心业务 
                    Object invoke = method.invoke(teamService, args); 
                    System.out.println("提交事务"); 
                    return invoke;
                }catch (Exception e){ 
                    System.out.println("回滚事务"); 
                    e.printStackTrace(); 
                    throw e; 
                }finally { 
                    System.out.println("finally---------"); 
                } 
            } 
        } 
    ); 
    //代理对象干活 
    proxyService.add(); 
    System.out.println(teamService.getClass()); 
    System.out.println(proxyService.getClass()+"--------"); 
}
}

2 结构化设计

方式1:

public class ProxyHandler implements InvocationHandler { 
    private IService service;//目标对象 
    private AOP aop;//切面 
    public ProxyHandler(IService service, AOP aop) { 
        this.service = service; 
        this.aop = aop; 
    }
    @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 main2(String[] args) { 
    //目标对象--被代理对象 
    TeamService teamService=new TeamService(); 
    //切面 
    AOP tranAop=new TranAOP(); 
    //返回代理对象 基于JDK的动态代理 
    IService proxyService= (IService) Proxy.newProxyInstance( 
        teamService.getClass().getClassLoader(), 
        teamService.getClass().getInterfaces(), 
        new ProxyHandler(teamService,tranAop) 
    ); 
    //代理对象干活 
    proxyService.add(); 
    System.out.println(teamService.getClass()
    System.out.println(proxyService.getClass()+"------"); 
}

方式2:

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。

3 基于CGLIB的动态代理

    Cglib代理,也叫做子类代理。在内存中构建一个子类对象从而实现对目标对象功能的扩展。
    JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用CGLIB实现。
    CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception。
    CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。

3.1 测试类

public class NBAService { 
    public int add(String name,int id){ 
        System.out.println("NBAService---- add----"); 
        return id; 
    } 
}
public static void main(String[] args) { 
    //目标对象:没有接口 
    NBAService nbaService=new NBAService(); 
    //创建代理对象:选择cglib动态代理 
    NBAService proxyService= (NBAService) Enhancer.create(
        nbaService.getClass(), 
        new MethodInterceptor() {
            //回调函数编写代理规则 
            @Override 
           public Object intercept(Object o, Method method, 
           Object[] objects, MethodProxy methodProxy) throws Throwable { 
                try { 
                    System.out.println("开始事务"); 
                     //核心 
                    Object invoke = methodProxy.invokeSuper(o, objects);
                    System.out.println("提交事务"); 
                    return invoke; 
                }catch (Exception e){ 
                    System.out.println("事务回滚"); 
                    throw e; 
                }finally { 
                    System.out.println("finally------------"); 
                } 
            } 
        }
    ); 
    //代理对象干活 
    int res=proxyService.add("huren",1001); 
    System.out.println(res); 
}

3.2 结构化设计方式

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); 
}
上一篇:aop 执行顺序


下一篇:切面AOP的切点@Pointcut用法