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