为什么选择AOP:
要了解AOP(面向方面的编程),我们需要了解软件开发中的“横切关注点”。 在每个项目中,都有一定数量的代码在多个类,多个模块中重复执行,例如几乎所有类和所有模块都需要记录日志。
这类代码降低了代码的可重用性,可维护性和可伸缩性。例如,如果您要使用该类并在不需要日志的其他地方重用它,则必须更改该类。 同样,如果更改了验证或日志记录,则无论使用什么地方,我们都必须改变几乎每个类。
一个类应该专注于它的核心功能,诸如日志记录,验证,事务之类的东西不是该类功能的一部分。 面向方面的编程是帮助我们消除这些交叉问题的范例。 它为我们提供了将我们的交叉代码与类分开的工具和方法。
代理模式:
我们可以创建对象的代理,该代理将处理交叉关注代码。代理模式有两种:
-
静态代理:
在这里我们为每个类创建一个代理对象。 这是不可行的
-
动态代理:
在此,通过反射动态创建代理。 此功能是从JDK 1.3中添加的。 动态代理构成Spring AOP的基本构建块
在这里,类Example1实现接口BasicFunc。
package com.somaniab.blog.ex;public class Example1 implements Basicfunc{@Overridepublic void method1() {System.out.println("executing method 1"); }}
这是接口Basicfunc
package com.somaniab.blog.ex;public interface Basicfunc{public void method1(); }
现在,如果要计算method1的执行时间,我们必须在方法本身中编写该代码,或者我们可以创建一个代理对象。 为了创建代理对象,我们创建一个Invocationhandler,如下所示:
package com.somaniab.blog.ex;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class MyInvocationHandler implements InvocationHandler{private Object target ;public MyInvocationHandler(Object target){this.target = target;}public Object getTarget() {return target;}public void setTarget(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] params)throws Throwable {long a = System.currentTimeMillis();Object result =method.invoke(target ,params);System.out.println("total time taken "+(System.currentTimeMillis()-a));return result;}}
在此调用处理程序中,我们调用实际方法并计算所需的时间。现在,在主类中,我们使用Proxy类创建代理对象。
package com.somaniab.blog.ex;import java.lang.reflect.Proxy;public class MainClass {public static void main(String[] args) {Example1 ex = new Example1();Basicfunc proxied =(Basicfunc)Proxy.newProxyInstance(MainClass.class.getClassLoader(),ex.getClass().getInterfaces() ,new MyInvocationHandler(ex));proxied.method1();}
}
为了创建Proxy,我们传递了classloader(几乎与原始类相同的classloader),接口和invocationHandler(在调用处理程序中传递了原始目标对象)。 原始类必须实现一个接口,只有接口中声明的那些方法才被代理,然后我们将代理转换为接口类型。
如果您收到这样的异常: java.lang.ClassCastException:$ Proxy0无法转换为com.somaniab.blog.ex.Example1 ,则意味着您的目标类未实现该接口。
在CGLib Proxy中,没有必要声明接口。 因此,这就是我们确保示例类仅为method1编写代码的方式,并且将执行时间计算代码保留在其中。 这是一个非常基本的示例,但它是Spring AOP的基础。 除了Spring AOP以外,其他实现aop的框架是AspectJ和JBOSS AOP
翻译自: https://www.javacodegeeks.com/2013/04/understanding-dynamic-proxy-spring-aop-basics.html