4. AOP
2019-10-12 本文已影响0人
月影追猎者
AOP (Aspect Oriented Programming),面向切面编程,通过预编译方式与运行期动态代理实现程序功能的统一维护的技术。利用AOP可以对业务逻辑进行隔离,使业务逻辑间耦合度降低,提高可重用性,提高开发效率。
动态代理
/**
* 接口
*/
public interface Subject {
void request();
}
/**
* 实体类
*/
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("核心方法");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理类
* 生成对象的代理对象
*/
public class DynamicProxy implements InvocationHandler {
private Object obj; // 被代理对象
public DynamicProxy(Object obj) {
this.obj = obj;
}
/**
* 生成obj的代理对象
*/
public Object getInstance() {
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
/**
* 执行obj任一方法时的通知设置
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object ret = null;
System.out.println("动态代理 - 前置通知");
try {
ret = method.invoke(obj, args); // 核心方法
System.out.println("动态代理 - 后置通知");
} catch (Exception e) {
System.out.println("动态代理 - 例外通知");
} finally {
System.out.println("动态代理 - 最终通知");
}
return ret;
}
}
public static void main(String[] args) {
Subject real = new RealSubject();
DynamicProxy proxy = new DynamicProxy(real);
Subject sub = (Subject) proxy.getInstance();
sub.request();
}
AOP
基于动态代理模式,将方法切出切面以进行统一控制。
- 编写相应的通知方法
- 在Spring中配置通知
public class AOP {
/**
* 切入点方法
* 无参,返回值类型void,方法体无代码
*/
public void pointcut() {
}
/**
* 前置通知
*/
public void before() {
System.out.println("AOP类前置通知方法");
}
/**
* 后置通知
*/
public void returning() {
System.out.println("AOP类后置通知方法");
}
/**
* 例外通知
*/
public void throwing() {
System.out.println("AOP类例外通知方法");
}
/**
* 最终通知
*/
public void after() {
System.out.println("AOP类最终通知方法");
}
}
引入依赖jar包
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
配置applicationContext.xml文件
<bean id="aop类id" class="AOP类全名"/>
<aop:config>
<aop:aspect id="切面id" ref="aop类id">
<!--
配置切入点
第一个*,返回值类型,*表示任意返回值类型
第二个*,类名,*表示任意类名
第三个*,方法名,*表示任意方法名
(..),形参类型,..表示任意形参类型
-->
<aop:pointcut id="切入点id" expression="execution(* 包名.*.*(..))"/>
<aop:before method="前置通知方法before" pointcut-ref="切入点id"/>
<aop:after-returning method="后置通知方法returning" pointcut-ref="切入点id"/>
<aop:after-throwing method="例外通知方法throwing" pointcut-ref="切入点id"/>
<aop:after method="最终通知方法after" pointcut-ref="切入点id"/>
</aop:aspect>
</aop:config>