AOP-举例场景-计算器运行计算方法的时候进行日志记录
面向切面编程举例场景:
计算器运行计算方法的时候进行日志记录
加日志记录:
1)直接编写在方法内部,不推荐,修改维护麻烦
日志记录:系统的辅助功能;
业务逻辑:系统核心功能
这样做,耦合
public interface Calculator { public int add(int i,int j); public int sub(int i,int j); public int mul(int i,int j); public int div(int i,int j); } public class MyMathCalculator implements Calculator { @Override public int add(int i, int j) { System.out.println("[add]方法开始调用,参数为【"+i+","+j+"】"); int result=i+j; System.out.println("[add]方法结束,结果为"+result); return result; } @Override public int sub(int i, int j) { System.out.println("[sub]方法开始调用,参数为【"+i+","+j+"】"); int result=i-j; System.out.println("[sub]方法结束,结果为"+result); return result; } @Override public int mul(int i, int j) { System.out.println("[mul]方法开始调用,参数为【"+i+","+j+"】"); int result=i*j; System.out.println("[mul]方法结束,结果为"+result); return result; } @Override public int div(int i, int j) { System.out.println("[div]方法开始调用,参数为【"+i+","+j+"】"); int result=i/j; System.out.println("[div]方法结束,结果为"+result); return result; } } @Test public void test1() { MyMathCalculator myMathCalculator=new MyMathCalculator(); myMathCalculator.add(1,2); myMathCalculator.div(10,2); }
[add]方法开始调用,参数为【1, 2】 [add]方法结束,结果为3 [div]方法开始调用,参数为【10, 2】 [div]方法结束,结果为5
2)我们希望的是
业务逻辑(核心功能)
日志模块:在核心功能运行期间,自己动态的加上
可以使用动态代理来将日志代码动态的在目标方法执行前后先进行执行
public class ProxyFactory { public static Object getProxyInstance(final Object obj) { Object proxy = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("[" + method.getName() + "]方法开始调用,参数为【" + Arrays.asList(args) + "】"); Object result = method.invoke(obj, args); System.out.println("[" + method.getName() + "]方法结束,结果为" + result); return result; } }); return proxy; } } @Test public void test1() { MyMathCalculator myMathCalculator=new MyMathCalculator(); Calculator proxyInstance =(Calculator) ProxyFactory.getProxyInstance(myMathCalculator); proxyInstance.add(1,2); proxyInstance.div(10,2); }
[add]方法开始调用,参数为【[1, 2]】 [add]方法结束,结果为3 [div]方法开始调用,参数为【[10, 2]】 [div]方法结束,结果为5
但是动态代理也有缺点:
1)写起来很难
2)Jdk默认的动态代理,如果目标对象没有实现任何接口,是无法为他创建代理对象的
(代理对象和被代理对象唯一能产生的关联就是实现了同一个接口)
Spring-AOP
可以利用Spring一句代码都不写的去创建动态代理,实现简单而且没有强制要求目标对象必须实现接口