AOP的术语
Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只 支持方法类型的连接点.
Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义.
Advice(通知/增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知.通知分为前置通知,
后置 通知,异常通知,最终通知,环绕通知(切面要完成的功能)
Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类 动态地添加一些方法或 Field.
Target(目标对象):代理的目标对象
Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程. spring 采用动态代理织入,
而 AspectJ 采用编译期织入和类装在期织入
Proxy(代理):一个类被 AOP 织入增强后,就产生一个结果代理类
Aspect(切面): 是切入点和通知(引介)的结合
依赖包的引入
这个也很坑,,
点击这里
Spring整合Junit进行测试
在测试类上加上这两句注解就可以对测试类里的对象进行依赖注入
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(“classpath:/aop编程/aopTest.xml”)
package aop编程;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
/**
* Created by Administrator on 2018/10/7.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/aop编程/aopTest.xml")
/*
有以上的注解,我们就可以直接在类上进行对象注入
Spring整合Junit
*/
public class testDemo {
@Resource(name="deleUser")
private userDao user;
@Test
public void testDemo1(){
user.add("小明");
user.deleUser("小明");
user.update("小明");
user.save();
}
}
切面类
首先的有一个切面类,才能对目标方法进行增强
在xml中
语法:<aop:aspect ref=“被增强的目标类”>配置通知 </aop:aspect>
切面类
package aop编程;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.omg.CORBA.Object;
/**
* Created by Administrator on 2018/10/7.
* 切面类
*/
public class aspect {
public void before1(JoinPoint joinPoint){
System.out.println("dele执行前的检测..."+joinPoint);
}
//参数名必须叫result,和xml里的after-retuing的result一样
public void after1(String result){
//这里加不了参数,,,也不知道为什么
System.out.println("执行add方法后..."+result);
}
public Object around(ProceedingJoinPoint joinpoint) throws Throwable {
System.out.println("调用update方法前");
Object obj= (Object) joinpoint.proceed();
System.out.println("调用update方法之后");
return obj;
}
public void afterThrow(Throwable ex){
System.out.println("异常被抛出...."+ex.getMessage());
}
public void finals(){
System.out.println("异常最终被通知");
}
}
先说一下我的xml文件
aopTest.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--需要映入aop的约束-->
<!--不扫描,切面类里面加了参数的方法就增强不了-->
<context:component-scan base-package="aop编程"/>
<bean id="deleUser" class="aop编程.userDao"></bean>
<bean id="userDao" class="aop编程.aspect"></bean>
<!--aop的配置-->
<aop:config>
<!--aop切入点表达式的配置,说明那些方法需要增强-->
<aop:pointcut expression="execution(* aop编程.userDao.deleUser(..))" id="pointcut1"/>
<aop:pointcut expression="execution(* aop编程.userDao.add(..))" id="pointcut2"/>
<aop:pointcut expression="execution(* aop编程.userDao.update(..))" id="pointcut3"/>
<aop:pointcut expression="execution(* aop编程.userDao.save(..))" id="pointcut4"/>
<!--配置切面-->
<aop:aspect ref="userDao">
<!--前置通知-->
<aop:before method="before1" pointcut-ref="pointcut1" />
<!--后置通知-->
<aop:after-returning method="after1" pointcut-ref="pointcut2" returning="result"/>
<!--环绕通知-->
<aop:around method="around" pointcut-ref="pointcut3" />
<!--retuing里的名字可以随便取,但是必须和after的参数名相同也叫result-->
<!--异常通知-->
<aop:after-throwing method="afterThrow" pointcut-ref="pointcut4" throwing="ex" />
<!--最终通知-->
<aop:after method="finals" pointcut-ref="pointcut4" />
</aop:aspect>
</aop:config>
</beans>
被增强的类userDao
package aop编程;
/**
* Created by Administrator on 2018/10/7.
*/
public class userDao {
public boolean deleUser(String name){
System.out.println(name+"被成功删除deleUser");
return true;
}
public void update(String name){
System.out.println(name+"被更新update");
}
public void save(){
System.out.println("调用userDao.save().....");
int num=1/0;
}
public String add(String name){
System.out.println(name+"被添加进来add");
return "aaaaa";
}
}
切点
即被增强的类中的方法,一般只需要在xml文件里的切面配置即可,之后调用
方法会自动被增强
<aop:pointcut expression=“execution(方法路径)” id=“切点名称”/>
这里说一下expression语法
方法前面的 * 是匹配所有返回类型
class.* 包含class类下的所有方法
*. *. *.method() 包含所有包下的子包的子包的method方法
class+.method() 包含class及其子类下的method方法
class.*od() 包含class下的以od结尾方法
前置通知
对所增强的方法,在执行之前进行的方法
xml中
<aop:before method="增强的方法" pointcut-ref="切点名" />
后置通知
对所增强的方法,在执行之前进行的方法
<aop:after-returning method=“增强的方法” pointcut-ref=“切点名” returning=“result”/>
这里的returning的名字必须和切面类的后置方法相同,相当与传给后置方法
以上面例子为例
//参数名必须叫result,和xml里的after-retuing的result一样
public void after1(String result){
//这里加不了参数,,,也不知道为什么
System.out.println("执行add方法后..."+result);
}
环绕通知方法
对所增强的方法,在执行之前及之后进行的方法
<aop:around method=“增强的方法” pointcut-ref=“切点名” />
相应的增强方法:
public Object around(ProceedingJoinPoint joinpoint) throws Throwable {
System.out.println("调用update方法前");
Object obj= (Object) joinpoint.proceed();//被增强的方法
System.out.println("调用update方法之后");
return obj;
}
异常通知
对所增强的方法,发生异常进行的方法
<aop:after-throwing method="增强的方法" pointcut-ref="切点名" throwing="ex" />
同样,throwing里的名字必须和切面类里的方法匹配
public void afterThrow(Throwable ex){
System.out.println("异常被抛出...."+ex.getMessage());
}
最终通知
这个无论程序怎样都会执行,相当于finally
<aop:after method="增强的方法" pointcut-ref="切点名" />
让我们看下运行结果把
对了,还有一点要注意一下,就是必须加上扫描,不然切面类里的方法
加了参数后,起不了增强作用
可以看见,程序发生了除零异常,程序正确运行