spring framework最牛的两大功能我认为是Ioc 以及AOP了。
现在说一波AOP的使用方法,一共有两个方法,一个是注解,另一个则是XML配置
需要依赖一波所需要的jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>,1.5.3</version>
</dependency>
版本自选也可以参考我的版本。spring.version为 4.3.11.RELEASE
首先简单地举个例子:
假如我要去吃饭,那么好,写个吃饭的方法:吃饭
那么吃饭之前是不是得有人帮你煮饭,吃完了饭是不是还得洗碗。而我们接口只有一个吃饭的方法,其他的事情我们交给aop去处理。
aop主要分为切点、切面。切点则为切入点,当程序跑到这个切入点的时候则执行切面方法,这个切入点可以精确到包、类、方法。
1;注解使用:
首先写我们的业务代码:
1.1写一个吃饭的程序
public interface TestAOP {
void eatingFood(String food);
void pee();
}
程序中还有一个尿尿的方法,我们当然是想尿尿的方法就自己做 不需要aop,所以我们的切点得精确到方法
1.2写一个实现类
@Component
public class TestAOPImpl implements TestAOP {
public void eatingFood(String food) {
System.out.println("I'm eating " + food);
}
public void pee() {
System.out.println("sheeeeee!");
}
}
component注解是将bean注入到 Ioc容器中,这就是强大的spring0
1.3aop方法
下面编写aop类和方法,吃饭之前的煮饭、吃饭后的洗碗,都交给aop。假如我是大佬,我可以认为这是我的保姆。
@Component
@Aspect
public class Aop {
@Pointcut("execution(* Test.TestAOP.eatingFood(..))")
public void pointCut_(){
}
@Before("pointCut_()")
public void before(){
System.out.println("cooking!!!!");
}
@After("pointCut_()")
public void after(){
System.out.println("washing dishes");
}
}
类上加上
@Aspect注解表示切面类
@Pointcut("execution(* Test.TestAOP.eatingFood(..))") 表示切入点,注意切点表达式不要看错了 前面有个 * 号 方法的参数有两个 . 我被这两个点坑过,老是执行不了切面方法,后面发现是参数没写那两个点。
当然也能精确到包、类 用 * 表示任意东西 如@Pointcut("execution(* Test.*.*(..))") 表示Test包下的任意类任意方法都会执行切面方法。这里我们仍然希望 尿尿的事情自己解决,所以,精确到吃饭的那个方法。
@Before("pointCut_()") 就是切点之前要执行的方法
@After("pointCut_()") 是切点执行之后要执行的方法
还有三个注解此处没有用到
@AfterReturning("pointCut_()") 也是方法结束之后执行,但是如果方法报错了的话就走这个方法
@AfterThrowing("pointCut_()") 可以定义一个方法,如果方法抛出异常,则执行这个方法
@Around("pointCut_()") 环绕通知: 绕开目标方法执行
执行顺序,判断切点后,执行 before ->目标方法->after->AfterReturning
如果出错
before->目标方法出错->after->AfterThrowing->catch Block
1.4配置编写spring配置文件
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 使用注解时要开启注解扫描 要扫描的包 -->
<context:component-scan base-package="Test"></context:component-scan>
<!-- <bean id="aop" class="Test.Aop"/>
<aop:config>
<aop:pointcut id="pc" expression="execution(* Test.TestAOP.eatingFood(..))"/>
<aop:aspect ref="aop">
<aop:before method="before" pointcut-ref="pc"/>
<aop:after method="after" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>-->
<!-- 开启aop注解方式 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
1.5编写main方法测试一波
public class AopRunning {
public static void main(String[] args){
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-aop.xml");
TestAOP aop=(TestAOP) applicationContext.getBean("testAOPImpl");
try {
aop.eatingFood("rice");
} catch (Exception e) {
System.out.println(".....");
}
aop.pee();
}
}
我们发现我们的eating方法已经被aop拦截 但是pee()还是该怎样就怎样
cooking!!!!
I'm eating rice
washing dishes
wash hand
sheeeeee!
2:xml配置形式
其实上文配置文件中有几行注释就是aop的注释,只要把那几个注释加上就行,就不用写注解。道理如注解一般不再累赘
<bean id="aop" class="Test.Aop"/>
<aop:config>
<aop:pointcut id="pc" expression="execution(* Test.TestAOP.eatingFood(..))"/>
<aop:aspect ref="aop">
<aop:before method="before" pointcut-ref="pc"/>
<aop:after method="after" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>