一、怎么实现动态代理?
1. 定义代理类,实现InvocationHandler接口;
2. 重写invoke( )方法,对方法进行增强业务操作。【插入前置通知、后置通知代码】
3. 创建一个动态代理对象:通过Proxy的静态方法——>
newProxyInstance(1.类加载器, 2.被代理对象实现的所有接口字节码数组, 3.本类对象);
4. 通过动态代理对象,调用目标方法。
AOP作用:降低业务逻辑耦合度,提高程序的可重用型。
应用场景:
@Transaction自动开启关闭事务。
@Async注解来执行异步方法。
二、 案例
1.原业务接口
import java.math.BigDecimal;
/**
* 被代理对象接口:出售电脑
*/
public interface SaleComputer {
/**
* 买电脑
*/
String pay(BigDecimal money);
void show();
}
2.原业务接口实现类
import java.math.BigDecimal;
public class SaleComputerImpl implements SaleComputer {
@Override
public String pay(BigDecimal money) {
System.out.println("客户支付了"+ money + "买了一台电脑");
return "联想电脑";
}
@Override
public void show() {
System.out.println("展示电脑");
}
}
3.增强业务类
/**
* 业务增强类
*/
public class MyAspect {
public void myBefore() {
System.out.println("原业务执行之前:执行增强业务逻辑");
}
public void myAfter() {
System.out.println("原业务执行之后:执行增强业务逻辑");
}
}
4.自定义代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 定义代理类
*/
public class MyInvocationHandler implements InvocationHandler {
private Object object;
public MyInvocationHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MyAspect myAspect = new MyAspect();
if (method.getName().equals("pay")) {
// 前置通知
myAspect.myBefore();
}
Object invoke = method.invoke(object, args);
if (method.getName().equals("show")) {
// 后置通知
myAspect.myAfter();
}
return invoke;
}
}
5.测试类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.math.BigDecimal;
/**
* AOP动态代理测试
*/
public class AopTest {
public static void main(String[] args) {
SaleComputer saleComputer = new SaleComputerImpl();
// 1.类加载器
ClassLoader classLoader = saleComputer.getClass().getClassLoader();
// 2.被代理对象实现的所有的接口的字节码数组。
Class<?>[] interfaces = saleComputer.getClass().getInterfaces();
// 3.代理类
InvocationHandler invocationHandler = new MyInvocationHandler(saleComputer);
// 生成动态代理对象
SaleComputer sc = (SaleComputer)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
// 调用目标方法
sc.pay(new BigDecimal(100.00));
sc.show();
}
}
打印结果
"C:\Program Files\Java\jdk1.8.0_261\bin\java.exe" ...
原业务执行之前:执行增强业务逻辑
客户支付了100买了一台电脑
展示电脑
原业务执行之后:执行增强业务逻辑
总结
.========================努力干吧!菜鸟。