三(一)、aop面向切面编程由来

概述:

其实就是AOP作用就是:把分散在各个地方的功能分离出来形成组件。这样理解起来非常抽象;

实例说明:

看如下代码,ArithmeticCaculatorImpl 实现了ArithmeticCaculator,也就是一个实现计算加、减、乘、除的一个功能;此时如果想在每个方法得到结果之前,插入日志,表示方法开启,计算完成之后,添加日志表示计算完成该如何实现。可以在每个方法的计算语句前后加上打印日志;

 1 public interface ArithmeticCaculator {
 2     
 3     int add(int i,int j);
 4     int sub(int i,int j);
 5     
 6     int mul(int i,int j);
 7     int div(int i,int j);
 8     
 9 
10 }
 1 public class ArithmeticCaculatorImpl implements ArithmeticCaculator {
 2 
 3     @Override
 4     public int add(int i, int j) {
 5         int result = i+j;
 6         return result;
 7     }
 8 
 9     @Override
10     public int sub(int i, int j) {
11         int result = i-j;
12         return result;
13     }
14 
15     @Override
16     public int mul(int i, int j) {
17         int result = i*j;
18         return result;
19     }
20 
21     @Override
22     public int div(int i, int j) {
23         int result = i/j;
24         return result;
25     }
26 
27 }

方案一手动日志

可以在每个方法的计算语句前后加上打印日志的解决方式。代码如下;

三(一)、aop面向切面编程由来
 1 public class ArithmeticCaculatorImpl implements ArithmeticCaculator {
 2 
 3     @Override
 4     public int add(int i, int j) {
 5         System.out.println("the method add begins with["+i+"+"+j+"]");
 6         int result = i+j;
 7         System.out.println("the method add begins with "+result);
 8         return result;
 9     }
10 
11     @Override
12     public int sub(int i, int j) {
13         System.out.println("the method add begins with["+i+"-"+j+"]");
14         int result = i-j;
15         System.out.println("the method add begins with "+result);
16         return result;
17     }
18 
19     @Override
20     public int mul(int i, int j) {
21         System.out.println("the method add begins with["+i+"*"+j+"]");
22         int result = i*j;
23         System.out.println("the method add begins with "+result);
24         return result;
25     }
26 
27     @Override
28     public int div(int i, int j) {
29         System.out.println("the method add begins with["+i+"/"+j+"]");
30         int result = i/j;
31         System.out.println("the method add begins with "+result);
32         return result;
33     }
34 
35 }
View Code

这种解决方式,维护起来非常麻烦;每添加一个计算方法(比如添加一个取模方法,就得加上对应的日志);还有一种办法就是,采用动态代理

方案二动态代理:

1.添加代理工厂:

 1 package lixiuming.spring.aop.helloworld;
 2 
 3 import java.lang.reflect.Proxy;
 4 
 5 public class ProxyFactory {
 6 
 7     // 调用此方法,返回一个代理类的对象,解决了问题一
 8     public static Object getProxyInstance(Object obj) {// obj为被代理类的对象
 9         ProxyHandler proxyHandler = new ProxyHandler();
10         proxyHandler.bind(obj);;
11         return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), proxyHandler);
12     }
13 }

2.绑定代理类

 1 package lixiuming.spring.aop.helloworld;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 import java.util.Arrays;
 6 
 7 public class ProxyHandler implements InvocationHandler {
 8 
 9     private Object obj;
10 
11     public void bind(Object obj) {
12         this.obj = obj;
13     }
14 
15     @Override
16     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
17         // TODO Auto-generated method stub
18 
19         String methodName = method.getName();
20         System.out.println("the method " + methodName + "begins with" + Arrays.asList(args));
21         Object result = method.invoke(obj, args);
22         System.out.println("the method " + methodName + "begins with" + result);
23         return method.invoke(obj, args);
24     }
25 
26 }

 

测试:

 1     public static void main(String[] args) {
 2 
 3         ArithmeticCaculator arithmeticCaculator1 = (ArithmeticCaculator) ProxyFactory
 4                 .getProxyInstance(new ArithmeticCaculatorImpl());
 5         int result11 = arithmeticCaculator1.add(1, 2);
 6         System.out.println("-->" + result11);
 7 
 8         int result22 = arithmeticCaculator1.div(4, 2);
 9         System.out.println("-->" + result22);
10 
11         int result33 = arithmeticCaculator1.mul(4, 2);
12         System.out.println("-->" + result33);
13 
14         int result44 = arithmeticCaculator1.sub(4, 2);
15         System.out.println("-->" + result44);
16 
17     }

运行结果:

the method addbegins with[1, 2]

the method addbegins with3

-->3

the method divbegins with[4, 2]

the method divbegins with2

-->2

the method mulbegins with[4, 2]

the method mulbegins with8

-->8

the method subbegins with[4, 2]

the method subbegins with2

-->2

 这个运行结果和 在每个方法的计算语句前后加上打印日志的解决方式 结果一样;但是配置还是不是那么灵活(比如想配置某个包下面的所有方法,都需要执行日志,那么每次调用该方法的动态代理等问题没有很好的解决)。spring提供了aop方式的解决方案;

方案三spring aop

实现代码放在下一篇三(二)、AOP配置中

 

上一篇:面试官问你Mybatis的Mapper代理 你能答多少


下一篇:集合框架-泛型-泛型方法