(八)Spring详解——代理实现

来源:互联网 发布:淘宝的id是什么 编辑:程序博客网 时间:2024/05/16 01:36

场景

    public void save() {        System.out.println("日志记录");        try {            System.out.println("事务开始");            System.out.println("事务提交");            System.out.println("事务结束");        } catch (Exception e) {            System.out.println("事务回滚");        }    }

日志,事务等大量重复代码。
实际开发中,业务是交叉的。
尝试解决办法——抽象成一个类的静态方法供调用
缺陷:编写业务逻辑的程序员需要了解日志,事务的使用,程序高耦合。
由此,AOP的思想出现了,实现了低耦合,高内聚。将核心代码与日志,事务等分离,将公共部分代码以切面的方式实现。
实现方式:代理模式
首先介绍一下代理模式:

静态代理

基于类继承的代理

 public class GoodsService {    public void save() {        System.out.println("doSave");    }}

通过继承重写方法,实现代理

public class GoodsServiceProxy extends GoodsService {    @Override    public void save() {        System.out.println("日志记录");        try {            System.out.println("事务开始");            super.save();            System.out.println("事务结束");        } catch (Exception e) {            System.out.println("事务回滚");        }    }}

基于接口的方式实现代理
1.创建一个被代理的接口,并在接口中声明被代理的方法
2.编写被代理类,实现被代理接口,实现业务的编写
3.创建针对接口的代理类实现被代理接口。通过被代理类实例和代理实例,在被代理方法中同时实现被代理类业务逻辑以及代理方法。

基于JDK的动态代理(基于接口)

    public static Object newProxyInstance(ClassLoader loader,                                          Class<?>[] interfaces,                                          InvocationHandler h)
     ClassLoader类加载器,代理类是动态生成的,类本身不存在,需要借用其他类的类加载器(一般是被代理对象的类加载器)     Class<?>被代理接口的数组     InvocationHandler动态代理类代理行为的接口

InvocationHandler抽象接口方法:
public Object invoke(Object proxy, Method method, Object[] args)
Object proxy动态生成的代理对象
method代理对象方法
args参数数组

首先创建代理接口,然后创建被代理对象实现代理接口。然后通过反射动态生成代理对象,实现动态代理

public class TestProxy {    public static void main(String[] args) {        final GoodsService service = new GoodsService();        GoodsServiceInterface s = (GoodsServiceInterface) Proxy                .newProxyInstance(service.getClass().getClassLoader(), service                        .getClass().getInterfaces(), new InvocationHandler() {                    @Override                    public Object invoke(Object proxy, Method method,                            Object[] args) throws Throwable {                        System.out.println("开始事务");                        Object o = method.invoke(service, args);                        System.out.println("提交事务");                        return o;                    }                });        s.save();    }}

基于CGLIB的方式实现动态代理

动态对类进行代理,使用方法拦截器的方式。
需要导入cglib的jar包
Enhancer生成代理的方法create

public static create(Class<T> type,callBack callback)

type:被代理类
callBack回调接口,生成动态代理对象调用的代理方法
代理行为的接口callback,一般使用其子接口MethodInterceptor(方法拦截器)
public Object intercept(Object arg0, Method arg1, Object[] arg2,MethodProxy arg3)
arg0被代理对象
arg1被代理方法
arg2方法参数列表
arg3方法的代理方法

public class TestProxy {    public static void main(String[] args) {        GoodsService service = (GoodsService) Enhancer.create(                GoodsService.class, new MethodInterceptor() {                    @Override                    public Object intercept(Object arg0, Method arg1,                            Object[] arg2, MethodProxy arg3) throws Throwable {                        System.out.println("日志记录");                        return arg3.invokeSuper(arg0, arg2);                    }                });        service.save();    }}
0 0