1.定义了接口SmartAnimal
package spring.aop;
/**
* ClassName: SmartAnimal
* Package: spring.aop
* Description:
*
* @Author 王文福
* @Create 2024/2/1 21:02
* @Version 1.0
*/
public interface SmartAnimal {
public abstract Double getSum(double num1, double num2);//加法
public abstract Double getSub(double num1, double num2);//减法
}
2.实现该接口,并重写接口的方法
package spring.aop;
/**
* ClassName: TestCal1
* Package: spring.aop
* Description:
*
* @Author 王文福
* @Create 2024/2/1 21:03
* @Version 1.0
*/
public class SmartAnimalTest implements SmartAnimal {
@Override
public Double getSum(double num1, double num2) {
System.out.println("方法内部打印result=" + (num1 + num2));
return num1 + num2;
}
@Override
public Double getSub(double num1, double num2) {
System.out.println("方法内部打印result=" + (num1 - num2));
return num1 - num2;
}
}
3.定义代理类,通过反射+动态代理
package spring.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* ClassName: VehicleProxyProvider
* Package: spring.aop
* Description:
*
* @Author 王文福
* @Create 2024/2/1 18:22
* @Version 1.0
*/
public class SmartAnimalProxyProvider<T> {
private T instance;//实现了T接口的对象实例
public SmartAnimalProxyProvider(T instance) {
this.instance = instance;//通过构造器初始化instance实例
}
/**
* 得到的那个代理对象
*
* @param :
* @return T
* @author "卒迹"
* @description TODO
* @date 18:59
*/
public T getProxy() {
/**
* 返回1个代理对象
*
* @param :
* @return T
* @author "卒迹"
* @description TODO
* @date 18:37
*/
//参数1:类的加载器
ClassLoader classLoader = instance.getClass().getClassLoader();
//参数2:得到要代理的对象/被执行对象的接口信息
Class<?>[] interfaces = instance.getClass().getInterfaces();
//参数3: 调用处理器/对象 有1个非常重要的方法invoke
//InvocationHandler是1个接口,使用匿名对象创建实现了该接口的对象实例
InvocationHandler invocationHandler = new InvocationHandler() {
/**
* @param proxy: 代理对象
* @param method: 代理对象调用方法时的那个方法
* @param args: 方法携带的参数
* @return Object
* @author "卒迹"
* @description TODO
* @date 18:53
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName() + "";
System.out.println("日志-方法名-" + methodName + "-" + "参数" + args[0] + " " + args[1]);
//通过反射调用该代理对象的方法,比如run方法
// 参数1:代理对象instance 参数2:方法携带的参数
Object invoke = method.invoke(instance, args);
System.out.println("日志-方法名-" + methodName + "-" + "结果result=" + (Double)invoke);
return invoke;
}
};
return (T) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
}
}
4.调用测试方法
package spring.aop;
/**
* ClassName: CalTest
* Package: spring.aop
* Description:
*
* @Author 王文福
* @Create 2024/2/1 21:13
* @Version 1.0
*/
public class CalTest {
public static void main(String[] args) {
//初始化代理对象
//<SmartAnimal> 定义运算的接口
//new SmartAnimalTest() 实现了SmartAnimal接口的对象实例
SmartAnimalProxyProvider<SmartAnimal> smartAnimalSmartAnimalProxyProvider
= new SmartAnimalProxyProvider<>(new SmartAnimalTest());
//得到该代理对象
SmartAnimal proxy = smartAnimalSmartAnimalProxyProvider.getProxy();
proxy.getSum(10, 20);//调用代理对象的方法
System.out.println("---------------------------------------------");
proxy.getSub(10, 22);
}
}
5.打印输出结果
分析:以上代码存在什么问题?
以上代码是写死在代理类中的,不利于复用和维护
解决方案:使用模板设计模式+动态绑定机制
package spring.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* ClassName: VehicleProxyProvider
* Package: spring.aop
* Description:
*
* @Author 王文福
* @Create 2024/2/1 18:22
* @Version 1.0
*/
public abstract class SmartAnimalProxyProvider<T> {
private T instance;//实现了T接口的对象实例
public SmartAnimalProxyProvider(T instance) {
this.instance = instance;//通过构造器初始化instance实例
}
public abstract void init(Object proxy, Method method, Object[] args);//前置处理通知
public abstract void post(Object proxy, Method method, Object[] args, Object invoke);//后置处理通知
public abstract void exception(Exception e, Object proxy, Method method, Object[] args);//异常处理通知
public abstract void finallyDispose(Object proxy, Method method, Object[] args);//异常finally处理
/**
* 得到的那个代理对象
*
* @param :
* @return T
* @author "卒迹"
* @description TODO
* @date 18:59
*/
public T getProxy() {
/**
* 返回1个代理对象
*
* @param :
* @return T
* @author "卒迹"
* @description TODO
* @date 18:37
*/
//参数1:类的加载器
ClassLoader classLoader = instance.getClass().getClassLoader();
//参数2:得到要代理的对象/被执行对象的接口信息
Class<?>[] interfaces = instance.getClass().getInterfaces();
//参数3: 调用处理器/对象 有1个非常重要的方法invoke
//InvocationHandler是1个接口,使用匿名对象创建实现了该接口的对象实例
InvocationHandler invocationHandler = new InvocationHandler() {
/**
* @param proxy: 代理对象
* @param method: 代理对象调用方法时的那个方法
* @param args: 方法携带的参数
* @return Object
* @author "卒迹"
* @description TODO
* @date 18:53
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
init(proxy, method, args);//前置处理
//通过反射调用该代理对象的方法,比如run方法
// 参数1:代理对象instance 参数2:方法携带的参数
Object invoke = method.invoke(instance, args);
post(proxy, method, args, invoke);//后置处理
return invoke;
} catch (Exception e) {
exception(e, proxy, method, args);//异常处理
throw new RuntimeException(e);
} finally {
finallyDispose(proxy, method, args);//finally处理
}
}
};
return (T) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
}
}
子类实现代理类的抽象方法(模板设计模式)
package spring.aop;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* ClassName: SmartAnimalProxyProviderTest
* Package: spring.aop
* Description:
*
* @Author 王文福
* @Create 2024/2/1 22:34
* @Version 1.0
*/
public class SmartAnimalProxyProviderTest extends SmartAnimalProxyProvider<SmartAnimal> {
public SmartAnimalProxyProviderTest(SmartAnimal instance) {
super(instance);
}
@Override
public void init(Object proxy, Method method, Object[] args) {
System.out.println("方法执行前-日志-方法名-" + method.getName() + "-参数 "
+ Arrays.asList(args)); //这里从AOP看,就是一个横切关注点-前置通知
}
@Override
public void post(Object proxy, Method method, Object[] args, Object result) {
System.out.println("方法执行正常结束-日志-方法名-" + method.getName() + "-结果result= "
+ result);//从AOP看, 也是一个横切关注点-返回通知
}
@Override
public void exception(Exception e, Object proxy, Method method, Object[] args) {
//如果反射执行方法时,出现异常,就会进入到catch{}
System.out.println("方法执行异常-日志-方法名-" + method.getName()
+ "-异常类型=" + e.getClass().getName());//从AOP看, 也是一个横切关注点-异常通知
}
@Override
public void finallyDispose(Object proxy, Method method, Object[] args) {
//从AOP的角度看, 也是一个横切关注点-最终通知
System.out.println("方法最终结束-日志-方法名-" + method.getName());
}
}
package spring.aop;
import java.util.Objects;
/**
* ClassName: CalTest
* Package: spring.aop
* Description:
*
* @Author 王文福
* @Create 2024/2/1 21:13
* @Version 1.0
*/
public class CalTest {
public static void main(String[] args) {
//初始化代理对象
//<SmartAnimal> 定义运算的接口
//new SmartAnimalTest() 实现了SmartAnimal接口的对象实例
SmartDog smartDog = new SmartDog();
//调用的是子类重写父类的抽象方法
SmartAnimalProxyProvider smartAnimalProxyProvider = new SmartAnimalProxyProviderTest(smartDog);
SmartAnimal proxy = (SmartAnimal) smartAnimalProxyProvider.getProxy();
proxy.getSum(10,20);
proxy.getSub(10,20);
}
}