Spring的AOP简介
什么是AOP
1. AOP为Aspect Oriented Programming的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
2. AOP是OOP(面对对象编程)的延续,利用AOP可以对业务逻辑的各个部分进行隔离。从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性和开发的效率。
AOP的作用及其优势
作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强
优势:减少重复代码,提高开发效率,并且便于维护
AOP底层实现
Jdk代理:基于接口的动态代理技术
jdk简单的实现:
public static void main(String[] args) {
//目标对象
final Target target = new Target();
//获取增强对象
final Advice advice = new Advice();
//动态代理,返回值就是动态生成的代理对象
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
//调用代理对象的任何方法实质上都是执行的invoke方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//增强前
advice.before();
//执行目标方法
Object invoke = method.invoke(target, args);
//增强后
advice.after();
return invoke;
}
});
proxy.save();
}
通知类:
public class Advice {
public void before() {
System.out.println("前置。。。。。。。");
}
public void after() {
System.out.println("后置。。。。。。。");
}
}
业务类:
public class Target implements TargetInterface {
public void save() {
System.out.println("iu给我布置了科学家不错");
}
}
Cglib代理:基于父类的动态代理技术
cglib简单的实现:
public static void main(String[] args) {
//目标对象
final Target target = new Target();
//获取增强对象
final Advice advice = new Advice();
//动态代理,返回值就是动态生成的代理对象 基于cglib
//1.创建增强器
Enhancer enhancer = new Enhancer();
//2.设置父类(目标)
enhancer.setSuperclass(Target.class);
//3.设置回调
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
advice.before();
Object invoke = method.invoke(target, objects);
advice.after();
return invoke;
}
});
//4.创建代理对象
Target proxy = (Target) enhancer.create();
proxy.save();
}
业务类:
public class Target{
public void save() {
System.out.println("iu给我布置了科学家不错");
}
}
通知类:
public class Advice {
public void before() {
System.out.println("前置。。。。。。。");
}
public void after() {
System.out.println("后置。。。。。。。");
}
}
图示:
AOP 相关概念
Spring 的 AOP 实现底层就是对上面的动态代理的代码进行了封装,封装后我们只需要对需要关注的部分进行代码编写,并通过配置的方式完成指定目标的方法增强。
AOP 常用的术语如下:
-
Target(目标对象):代理的目标对象
-
Proxy (代理):一个类被 AOP 织入增强后,就产生一个结果代理类
-
Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
-
Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义
-
Advice(通知/ 增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知
-
Aspect(切面):是切入点和通知(引介)的结合
-
Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入
完成一个小案例:
通知类:
public class Advice {
public void start() {
System.out.println("开启事务");
}
public void commit() {
System.out.println("提交事务");
}
public void rollback() {
System.out.println("回滚事务");
}
public void close() {
System.out.println("释放资源");
}
}
业务:
public interface Service {
/**
* 转账业务
*/
void transfer();
}
----------------------------------------------------------------------------
public class ServiceImpl implements Service {
/**
* 转载业务方法
*/
public void transfer() {
//业务逻辑
System.out.println("张三减少500元");
// int i = 1/0; //手动制造异常
System.out.println("李四增加500元");
}
}
动态代理工具类:
public class ProxyUtil {
//定义方法返回Service代理
public static Service getInstance() {
//创建目标对象
final Service service = new ServiceImpl();
//获取增强对象
final Advice advice = new Advice();
//创建动态代理
//参数:代理对象类加载器、字节码接口数组、代理实例的调用处理程序实现
Service instance = (Service) Proxy.newProxyInstance(service.getClass().getClassLoader(),
service.getClass().getInterfaces(),
new InvocationHandler() {
//动态代理,返回值就是动态生成的代理对象
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = null;
try {
//前置增强
advice.start();
//目标执行
invoke = method.invoke(service, args);
//后置增强
advice.commit();
} catch (Exception e) {
e.printStackTrace();
advice.rollback();
} finally {
advice.close();
}
return invoke;
}
});
return instance;
}
}
测试:
public class Test {
public static void main(String[] args) {
Service service = ProxyUtil.getInstance();
service.transfer();
}
}