消除迷宫:异境入侵官方中文版
· 2025-11-02
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程
切面:切面是一个类如:事务、日志、安全性的框架,权限等类就是切面
通知:切面中的方法就是通知
连接点:客户端调用的方法就是连接点
切入点:只有符合切入点的条件,才能让通知和目标方法结合在一起,满足一定条件才会执行目标方法,这里的条件表达式就是切入点
目标对象:目标对象就是被代理对象也就是target
AOP代理:AOP代理就是代理对象
织入:形成代理对象方法体的过程

意义:

说明:
代理类程序员自己写。
代理类和被代理类实现同一个接口,代理类调用被代理类方法,并提供额外的方法。

程序运行时,运用反射机制生成代理类。
接口

目标类

拦截器
拦截器对象是动态代理要用到的一个参数,实现对松耦合的对象中的方法进行有序排列调用

target参数代表被代理对象,也就是实现类
客户端
public class PersonDaoTest {
public void testJDKProxy(){
Object target = new PersonDaoImpl();
Transaction transaction = new Transaction();
/**
* 创建一个拦截器
*/
PersonDaoInterceptor interceptor = new PersonDaoInterceptor(target, transaction);
/**
* 1、目标类的类加载器
* 2、目标类实现的所有的接口
* 3、拦截器
*/
PersonDao personDao = (PersonDao)Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(), interceptor);
personDao.savePerson();
}}
因为代理对象和目标类一样,同样的实现了接口,所以接口中有多少方法,代理对象中就有多少个方法,名称和接口中的方法的名称一样。
当在客户端,代理对象调用方法的时候,进入到了invoke方法
当在客户端,代理对象调用方法的时候,进入到了invoke方法,这个时候,method参数就是代理对象调用的方法。
代理对象的方法体的内容就是invoke方法体的内容
代理对象的方法体:
流程图

作用:把目标类和事务松耦合。
没有接口
PersonDaoImpl.java
public class PersonDaoImpl{
public void savePerson() {
System.out.println("save person");
}
public void updatePerson(){
System.out.println("update person");
}}
PersonDaoInterceptor.java
public class PersonDaoInterceptor implements MethodInterceptor{
private Object target;
private Transaction transaction;
/**
* 产生代理类
* @return
*/
public Object createProxy(){
Enhancer enhancer = new Enhancer();
//设置代理类的父类是目标类
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();}
public PersonDaoInterceptor(Object target, Transaction transaction) {
this.target = target;
this.transaction = transaction;
}
public Object intercept(Object arg0, Method method, Object[] arg2,
MethodProxy arg3) throws Throwable {
if(method.getName().equals("savePerson")
||method.getName().equals("updatePerson")){
this.transaction.beginTransaction();
method.invoke(target, arg2);
this.transaction.commit();
}else{
method.invoke(target, arg2);
}
return null;
}}
PersonDaoTest.java
public class PersonDaoTest {
@Test
public void testJDKProxy(){
Object target = new PersonDaoImpl();
Transaction transaction = new Transaction();
/**
* 创建一个拦截器
*/
PersonDaoInterceptor interceptor = new PersonDaoInterceptor(target, transaction);
PersonDaoImpl proxy = (PersonDaoImpl)interceptor.createProxy();
proxy.savePerson();
}
}
目标接口

目标类

切面

Spring的配置文件

执行流程

说明:
getBean的参数在xml中对应的类就是目标类

后面有问号的内容代表可以不写
一个*代表该位置任意类型,..代表任意类型的任意个数参数代表所有的公共方法,一个.代表该位置有一个或多个任意类型

代表所有的以set开头的方法

代表com.xyz.service包下的AccoutService类的所有的方法

代表com.xyz.service包下的所有的类的所有的方法

代表com.xyz.service包及子包下的所有的类的所有的方法

代表com.itheima.spring.aop.xml包下的所有的类的有三个参数,第一个参数为Long,第二个参数为String,第三个参数为任意类型的所有的方法




前置通知
在目标方法执行之前执行。


前置通知也可以是无参方法,其他通知也是
后置通知
在目标方法执行之后执行,可以获取目标方法的返回值,当目标方法遇到异常,不执行


最终通知
无论目标方法是否遇到异常都会执行,相当于代码中的finally
异常通知
获取目标方法抛出的异常


环绕通知
能够控制目标方法的执行


输出aaa,执行前置通知,执行目标方法(如果有异常,执行异常通知),执行后置通知,执行最终通知,输出bbb
如果joinPoint.proceed()方法不写,则环绕通知就不会执行