实例分析,AOP的静态代理和动态代理
源码获取github
1.什么是AOP?
Aspect Oriented Programming with Spring 面向切面(方面)编程
- 面向切面编程是面向对象编程的一个补充而已
- 白话:我的理解—->在不改变原来的代码的基础上增强(增加)新的功能
2.代码结构
3.情景描述引发静态代理
如果现在让你完成一个2个数的四则运算
核心业务完成
package com.hs.service; /** * 对外提供的核心业务,完成了加法/减法/乘法/除法运算 */ public interface ArithmeticService { int add(int x, int y); int sub(int x, int y); int mul(int x, int y); int div(int x, int y); }
package com.hs.service; /** * 核心代码 */ public class ArithmeticServiceImpl implements ArithmeticService { @Override public int add(int x, int y) { //核心代码 int result = x + y; return result; } @Override public int sub(int x, int y) { int result = x - y; return result; } @Override public int mul(int x, int y) { int result = x * y; return result; } @Override public int div(int x, int y) { int result = x / y; return result; } }
完成了,和尚—>技术经理—>定义接口,悟空程序员—>接口实现类
交工客户龙王,龙王需要显示传递数据的信息功能—>和尚—>悟空完成客户需求,但是万一如果又不要这个功能呢,现在引出静态代理,在核心代码的基础上增加新的功能
package com.hs.service; /** * 新增加的功能,采用静态代理 */ public class ArithmeticServiceLogImpl implements ArithmeticService { //声明一个核心代码类的变量,为了后面方便调用核心代码的功能 private ArithmeticServiceImpl asc = new ArithmeticServiceImpl(); @Override public int add(int x, int y) { //后增加的某个功能 System.out.println("加法传递的参数===>x="+x+",y="+y); // 然后调用核心代码的功能 return asc.add(2, 3); } @Override public int sub(int x, int y) { System.out.println("减法传递的参数===>x="+x+",y="+y); return asc.sub(2, 3); } @Override public int mul(int x, int y) { System.out.println("乘法传递的参数===>x="+x+",y="+y); return asc.mul(2, 3); } @Override public int div(int x, int y) { System.out.println("除法传递的参数===>x="+x+",y="+y); return asc.mul(2, 3); } }
测试:
package com.hs.test;
import com.hs.proxy.ArithmeticServiceProxy;
import com.hs.service.ArithmeticService;
import com.hs.service.ArithmeticServiceImpl;
import org.junit.Before;
import org.junit.Test;
import java.lang.reflect.Proxy;
public class ArithmeticServiceTest {
private ArithmeticService arithmeticService;
@Before //在每个单元测试运行之前都要进行这个方法
public void init() {
this.arithmeticService = new ArithmeticServiceLogImpl();//new ArithmeticServiceImpl(); //想用哪个功能就实例化哪个类
}
@Test
public void testAddMethod() {
int result = this.arithmeticService.add(2, 3);
System.out.println(result);
}
}
4.动态代理
接口和核心代码不变,
代理类:
package com.hs.proxy;
import com.hs.service.ArithmeticService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* 代理类
*/
public class ArithmeticServiceProxy implements InvocationHandler {
//定义一个接口变量
private ArithmeticService arithmeticService;
public ArithmeticServiceProxy(ArithmeticService arithmeticService) {
this.arithmeticService = arithmeticService;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//写了某个功能,不管程序有没有错误都执行
System.out.println("在运行方法[" + method.getName() + "]之前执行,传递的参数为" + Arrays.asList(args));
Object result = null;
try {
result = method.invoke(this.arithmeticService, args);
//写了某个功能,只有程序没有错误才执行
System.out.println("运行方法成功,结果为:"+result);
} catch (Exception e) {
e.printStackTrace();
//写了某个功能,程序有错误的时候才执行
System.out.println("执行的方法错误");
}
//写了某个功能,不管程序有没有错误都执行
System.out.println("在运行方法之后执行");
return result;
}
}
测试
package com.hs.test;
import com.hs.proxy.ArithmeticServiceProxy;
import com.hs.service.ArithmeticService;
import com.hs.service.ArithmeticServiceImpl;
import org.junit.Before;
import org.junit.Test;
import java.lang.reflect.Proxy;
public class ArithmeticServiceTest {
private ArithmeticService arithmeticService;
@Before //再每个单元测试运行之前都要进行这个方法
public void init() {
this.arithmeticService = new ArithmeticServiceImpl(); //想用哪个功能就实例化哪个
}
/**
* 动态代理
*/
@Test
public void test01() {
//实例化代理类
ArithmeticServiceProxy asp = new ArithmeticServiceProxy(this.arithmeticService);
// 固定写法
ArithmeticService as = (ArithmeticService) Proxy.newProxyInstance(ArithmeticServiceImpl.class.getClassLoader(), ArithmeticServiceImpl.class.getInterfaces(), asp);
int result = as.div(10, 1);
System.out.println(result);
}
}