Spring AOP的概述
目录
AOP的概念
AOP的概念: Aspect-Oriented Programming(面向切面编程)的简称。用来描述分散在对象,类或函数中的横切面。
这也是为什么我们称它为面向切面编程,它是横向的,就像在一个业务逻辑横切一刀。对于它的某一个方法进行监控和加强一样。从关注点中分离出横切关注点是面向切面的程序设计的核心概念。可以通过预编译和运行期动态代理的方式对我们的源代码进行监控。使得业务逻辑的执行和性能的优化分离开,可以让我们在编写业务逻辑的时候专注于业务逻辑的实现,而将对于我们的业务逻辑的功能增强,例如日志监控,交由其他代理类进行实现。这样我们的业务逻辑代码中就不再含有针对特定领域问题代码的调用。我们的业务逻辑的维护工作就交给了我们的代理类来进行完成了。
既然说到了代理类,那么我们就需要介绍一下AOP应用到了设计模式中代理模式
代理模式: 给某一个对象提供一个代理对象,代理对象控制了原对象的引用。就像一个人去代替另一个人去做一件事情,但是这个人可以对这件事情进行一定的监控和加强。通过对于代理模式的分析,我们可以推论出。它实际上和我们在Spring MVC中接触到的拦截器很相似。拦截器拦截请求就如同代理对象执行相应的目标对象的方法。实际上对于目标对象的方法的执行交给了代理对象来执行。
举个例子,如果我们登录一个网站。网站会根据我们的身份为我们提供不同的工作,我们可以在目标类中写入如何进行登录验证密码,返回一个值。这个值是我们的身份标识,例如会员,普通用户。这个时候代理类代理了我们的目标类并通过登录验证获取到了返回值,根据不同的返回值对我们的请求进行相应的加强。
现在我来介绍一下关于Spring AOP中的一些名词概念。
1.连接点:业务逻辑中被拦截的点(SpringAOP中指的是方法)
2. 切点:匹配连接点的表达式,通过切点来设置那些连接点需要被拦截代理。
3. 切面:需要被拦截代理的连接点构成了一个切面。
4. 通知:AOP中对连接点进行代理时所进行的操作。
5. 目标对象:连接点所在的对象就是目标对象。
6. 代理对象:对目标对象进行代理的对象。
Java动态代理
那么接下来我来演示一下关于Java动态代理机制的运行,这里面涉及到了一个InvocationHandler接口,这个接口是非常关键的。实际上AOP的实现原理底层就是Java的动态代理机制。
首先我们来声明一个接口
package com.xt.spring.context.aop.dynamic;
public interface Person {
public void run();
}
然后用一个Coder类来实现这个接口
package com.xt.spring.context.aop.dynamic;
public class Coder implements Person{
public void run() {
System.out.println("the coder is running");
}
}
接下里我声明了一个中介类,作为代理对象和目标对象的中介,它声明了如何对目标对象的方法进行加强,同时它需要持有一个目标对象,这个中介类需要实现InvocationHandler接口并实现其中invoke方法。之后我们对于目标对象的方法调用实际上都是跳到这个最终的代理类的invoke方法中,通过反射的形式进行实现我们要加强的方法。
package com.xt.spring.context.aop.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyTest implements InvocationHandler{
private Object obj;
public ProxyTest(Object obj){
this.obj = obj;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法执行前的时间: "+System.currentTimeMillis());
Object result = method.invoke(this.obj, args);
System.out.println("方法执行后的时间: "+System.currentTimeMillis());
return result;
}
}
接下来我们来对我们的代码进行测试
package com.xt.spring.context.aop.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class MyTest {
public static void main(String[] args) {
Person person = new Coder();
InvocationHandler handler = new ProxyTest(person);
Person proxy = (Person)Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), handler);
proxy.run();
}
}
首先我们通过接口回调声明我们的person对象并交给我们中介类handler进行持有。
InvocationHandler handler = new ProxyTest(person);
接下来就是代理对象的生成过程了,这个过程实际上是很复杂的。主要由
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
完成,它需要一个类加载器,目标类实现的接口 ,以及一个中间类指明如何对目标对象进行一个加强。
首先这个方法会为我们生成一个代理类,这个代理类就是根据java的动态代理原理将我们的目标对象的方法写入到代理类中。在这个代理类会调用我们的handler中的invoke方法对相应的方法进行加强。当我们在此使用方法时,实际时就是通过这个代理对象来调用方法而不是通过最开始的person对象调用方法了。实际上通过对代理类的反编译代码可以看出,底层的方法依旧调用了Invoke方法。
这就是java动态代理,它在aop的实现中起到了至关重要的作用。
Spring AOP代码举例
关于Spring AOP代码的实现,我在这篇文章中进行了举例