AOP详解
AOP中的相关概念
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。
简单的来说:
-
利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
-
通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
例如:我需要在用户登陆模块新增一个权限判断的功能,通过面向切面就能完美实现
一些比较专业的概念定义:
-
Aspect(切面)
: Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的
Advice。 -
Joint point(连接点
):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。 -
Pointcut(切点
):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。 -
Advice(增强)
:Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。 -
Target(目标对象)
:织入 Advice 的目标对象.。 -
Weaving(织入)
:将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程
AOP底层原理是什么?
AOP底层使用动态代理,分为有接口和无接口两种情况进行动态代理
1)有接口情况
:JDK动态代理——调用newProxyInstance方法
2)无接口情况
:
JDK动态代理
调用newProxyInstance方法
该方法有三个参数
第一参数
:类加载器第二参数
:增加方法所在的类第三参数
:实现InvocationHandler接口,创建代理对象,写增强的方法
案例
1)创建接口,定义方法
package com.springAOP;
public interface UserDao {
public int add(int a ,int b);
public String updata (String id);
}
2)创建接口实现类,实现方法
package com.springAOP;
public class UserDaoImpl implements UserDao{
@Override
public int add(int a, int b) {
return a+b;
}
@Override
public String updata(String id) {
return id;
}
}
3)使用Proxy类创建接口代理对象
package com.springAOP;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class JDKProxy {
public static void main(String[] args) {
// 创建接口实现类代理
Class[] interfaces = {UserDao.class};
/**
* 三个参数
* 1.系统类加载器,通过ClassLoader.getSystemClassLoader()获得
* 2.需要增强方法所在的类,这个类实现的接口
* 3.实现InvocationHandler接口,增强方法体
*/
UserDao userDao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(new UserDaoImpl()));
// int add = userDao1.add(1, 2);
/**
* 测试add和updata方法
*/
System.out.println("add返回值:" + userDao.add(3, 5));
System.out.println("-------------------------------------");
System.out.println("updata返回值:" + userDao.updata("test"));
}
}
//创建代理对象代码
class UserDaoProxy implements InvocationHandler {
// 把创建的是谁的代理对象,把谁传递过来,该案例中创建的是UserDaoImpl的代理对象,写的通用一点就用object
// 有参数构造传递
private Object obj;
public UserDaoProxy(Object obj) {
this.obj = obj;
}
//增强的逻辑,目前逻辑是在方法执行前后做一个输出
@Override
/**
* proxy:代理对象
* method:当前方法
* args:参数值列表
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 方法之前
System.out.println("方法之前执行......" + method.getName() + "传递的参数:" + Arrays.toString(args));
// 执行被增强的方法
/**
* invoke:
* 第一个为对象
* 第二个为参数
*/
Object invoke = method.invoke(obj, args);
if (method.getName().equals("add")) {
System.out.println("执行的是add方法");
} else if (method.getName().equals("updata")) {
System.out.println("执行的是updata方法");
}
// 方法之后
System.out.println("方法之后执行" + obj);
return invoke;
}
}
spring帮我们把aop代码做了封装,我们直接进行配置就行,后续再更新