Spring AOP动态代理实例代码详解

AOP的好处:

切面编程可以把业务逻辑代码跟系统服务分离,developer只要专注于开发业务逻辑就可以了。 

Spring AOP实现方式 (基于动态代理实现):

1. JDK动态代理(基于接口interface实现);

2 CGLIB动态代理(基于具体实现类,创建代理子类方式实现)

AOP的运用场景有:

事务处理,日志打印,权限认证,全局异常捕获等


1. JDK动态代理通过反射来接收代理的类,但是被代理的类必须实现接口,核心是InvocationHandler和Proxy类

@Slf4j
public class UserServiceInvocationHandler implements InvocationHandler {
 
    private Object target;
 
    public void setTarget(Object target) {
        this.target = target;
    }
 
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
 
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log.info("start method - {}", method.getName());
        log.info("args - ");
        for (Object o : args) {
            log.info(o.toString());
        }
        Object res = method.invoke(target, args);
        log.info("complete method - {}", method.getName());
        return res;
    }
 
    // TODO - testing
    public static void main(String[] args) {
        UserServiceInvocationHandler handler = new UserServiceInvocationHandler();
        handler.setTarget(new UserServiceImpl());
        UserService userService = (UserService) handler.getProxy(); // JDK动态代理只能通过接口,所以这边只能强制转类型为对应的接口
        userService.add(new User(UUID.randomUUID().toString(), "Weijie Chen", 36));
    }
}

2. cglib动态代理的类一般是没有实现接口的类,cglib是一个代码生成类库,可以在运行时动态生成某个类的子类,所以,cglib是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用cglib来做动态代理的, 主要的CGLIB工具类有Enhancer, MethodInterceptor, MethodProxy

@Slf4j
public class CglibDynamicProxy implements MethodInterceptor {
 
    public Object createProxy(Object target){
        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(target.getClass()); // create parent class
        enhancer.setCallback(this);
        return enhancer.create();
 
    }
 
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        log.info("before executing method - " + method.getName());
        log.info("this is a tag before method executing...");
        Object obj= proxy.invokeSuper(o, args);
        log.info("this is a tag after method executing...");
        log.info("after executing method - " + method.getName());
        return obj;
    }
 
}
 
@Slf4j
class CglibDynamicProxyTester {
 
    public void test1() {
        log.warn("method test1 is running.");
    }
 
    public void test2() {
        log.warn("method test2 is running.");
    }
 
    // TODO - testing
    public static void main(String[] args) {
        // 创建代理类
        CglibDynamicProxy proxy = new CglibDynamicProxy();
        // 根据服务类创建被代理类的代理子类
        CglibDynamicProxyTester proxyObj = (CglibDynamicProxyTester) proxy.createProxy(new CglibDynamicProxyTester());
        proxyObj.test1();
        log.warn("========================== this is a line ===========================");
        proxyObj.test2();
    }
}

console 打印:

> Task :CglibDynamicProxyTester.main()
20:34:17.087 [main] INFO com.example.interview.user.proxy.CglibDynamicProxy -- before executing method - test1
20:34:17.089 [main] INFO com.example.interview.user.proxy.CglibDynamicProxy -- this is a tag before method executing...
20:34:17.102 [main] WARN com.example.interview.user.proxy.CglibDynamicProxyTester -- method test1 is running.
20:34:17.102 [main] INFO com.example.interview.user.proxy.CglibDynamicProxy -- this is a tag after method executing...
20:34:17.102 [main] INFO com.example.interview.user.proxy.CglibDynamicProxy -- after executing method - test1
20:34:17.102 [main] WARN com.example.interview.user.proxy.CglibDynamicProxyTester -- ========================== this is a line ===========================
20:34:17.102 [main] INFO com.example.interview.user.proxy.CglibDynamicProxy -- before executing method - test2
20:34:17.102 [main] INFO com.example.interview.user.proxy.CglibDynamicProxy -- this is a tag before method executing...
20:34:17.102 [main] WARN com.example.interview.user.proxy.CglibDynamicProxyTester -- method test2 is running.
20:34:17.103 [main] INFO com.example.interview.user.proxy.CglibDynamicProxy -- this is a tag after method executing...
20:34:17.103 [main] INFO com.example.interview.user.proxy.CglibDynamicProxy -- after executing method - test2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值