动态代理

2022-12-26 15:39:51 浏览数 (1)

  • 在原有程序不变的情况下通过动态代理增加新的功能(功能增强)
  • 减少代码的重复
  • 专注业务逻辑代码
  • 解耦合,让业务功能和日志,事务非业务功能分离

jdk动态代理实现案例

  • 使用JDK中的Proxy,Method,InvocationHanderl创建对象。
  • JDK动态代理要求目标类必须实现接口

SomeService

代码语言:javascript复制
public interface SomeService {
    void doSome();
    void doOther();
}

SomeServiceImpl

代码语言:javascript复制
public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome() {

        System.out.println("执行业务方法doSome");

    }

    @Override
    public void doOther() {

        System.out.println("执行业务方法doOther");

    }

ServiceTools

代码语言:javascript复制
import java.text.SimpleDateFormat;
import java.util.Date;

public class ServiceTools {
    public static void doLog(){
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        String format = simpleDateFormat.format(date);
        System.out.println("非业务方法,方法的执行时间:" format);
    }
    public static void doTrans(){
        System.out.println("非业务方法,方法执行完毕后提交事务");
    }

}

MyInvocationHandler

代码语言:javascript复制
import com.bjpowernode.util.ServiceTools;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {
    private Object target;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 通过代理对象执行方法时,会调用invoke()
        System.out.println("执行了MyInvocationHandler中的invoke()方法");
        String methodName = method.getName(); //doSome , doOther
        Object res = null;
        if ("doSome".equals(methodName)) {
            ServiceTools.doLog();
            res = method.invoke(target, args); //SomeServiceImpl.doOther(), doSome()
            ServiceTools.doTrans();
        } else {
            res = method.invoke(target, args);
        }
        return res;
    }
}

MyApp

代码语言:javascript复制
import com.bjpowernode.handler.MyInvocationHandler;
import com.bjpowernode.service.SomeService;
import com.bjpowernode.service.impl.SomeServiceImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class MyApp {
    public static void main(String[] args) {
        // 使用jdk的Proxy创建代理对象
        SomeService someService = new SomeServiceImpl();
        // 创建InvocationHandler对象
        InvocationHandler invocationHandler = new MyInvocationHandler(someService);
        // 使用Proxy创建代理
        SomeService proxy = (SomeService) Proxy.newProxyInstance(someService.getClass().getClassLoader(),
                someService.getClass().getInterfaces(), invocationHandler);
        // 通过代理执行方法,会调用handler中的invoke()方法
        proxy.doOther();
        System.out.println("------------------------");
        proxy.doSome();
    }
}

运行结果

代码语言:javascript复制
执行了MyInvocationHandler中的invoke()方法
执行业务方法doOther
------------------------
执行了MyInvocationHandler中的invoke()方法
非业务方法,方法的执行时间:2022-02-24 13:05:12:283
执行业务方法doSome
非业务方法,方法执行完毕后提交事务

CGLB动态代理

  • 第三方工具库,创建代理对象,原理是继承。通过继承目标类,创建子类
  • 子类就是代理对象,要求目标类不能是final的,方法也不能是final的

aspectj

aspectj框架也可实现AOP功能增强,具体可看spring中笔记

0 人点赞