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

本文探讨了在软件开发中如何利用AOP思想和代理模式来解决日志记录和事务管理等重复性代码问题,通过具体示例展示了静态代理、JDK动态代理及CGLIB动态代理的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

场景

    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();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值