Spring-AOP
AOP操作
百度百科:在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP的三种通知类型
- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知
一般基于AspectJ实现AOP操作
百度百科:AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
基于注解实现AspectJ的AOP操作
- 切入点表达式
- execution(权限修饰符 返回类型 类全路径 方法名称 参数列表)
- 对某一个方法进行增强 execution( * com.ws.spring.dao.BookDao. add(...))
- 对所有方法进行增强 exeuction( * com.ws.spring.dao.BookDao. *(...))
- 对某一个包内所有类以及包里面的所有方法进行增强 execution( * com.ws.spring.dao. *(...))
案例
被增强的类
package com.ws.spring.aop;
import org.springframework.stereotype.Component;
/**
* 被增强的类
*/
@Component
public class Users {
public void add(){
// int i = 10/0;
System.out.println("users add ...");
}
}
增强类1
package com.ws.spring.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* 增强业务的类
*/
@Aspect //生成代理对象
@Component //生成对象
@Order(1) //控制增强类的优先级
public class UsersProxy {
//相同的切入点的抽取
@Pointcut(value = "execution(* com.ws.spring.aop.Users.add(..))")
public void pointDemo(){
}
//配置不同类型的通知
//前置通知
@Before(value = "pointDemo()")
public void before(){
System.out.println("before ...");
}
//后置通知
@After(value = "pointDemo()")
public void after(){
System.out.println("after ...");
}
//方法返回值之后执行
@AfterReturning(value = "pointDemo()")
public void afterReturning(){
System.out.println("afterReturning ...");
}
//异常通知
@AfterThrowing(value = "pointDemo()")
public void afterThrowing(){
System.out.println("afterThrowing ...");
}
//环绕通知
@Around(value = "pointDemo()")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕之前 ...");
//执行被增强的方法
proceedingJoinPoint.proceed();
System.out.println("环绕之后 ...");
}
}
bean.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: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="com.ws.spring"></context:component-scan>
<!-- 开启 AspectJ 生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
测试
package com.ws.spring.test;
import com.ws.spring.aop.Users;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAop {
@Test
public void testAopAnno(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Users users = context.getBean("users", Users.class);
users.add();
}
}
通过以上程序,可以实现AOP编程,效果如下
公共切入点抽取
通过@Piontcut注解实现抽取公共切入点,在其他方法里面直接调用带此注解的方法即可
//相同的切入点的抽取
@Pointcut(value = "execution(* com.ws.spring.aop.Users.add(..))")
public void pointDemo(){
}
//配置不同类型的通知
//前置通知
@Before(value = "pointDemo()")
public void before(){
System.out.println("before ...");
}
设置多个增强类的优先级
通过@Order注解来设置一个被增强类的多个增强类之间的优先级
package com.ws.spring.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Order(3) //控制增强类的优先级
public class PersonProxy {
@Before(value = "execution(* com.ws.spring.aop.Users.add(..))")
public void before(){
System.out.println("person before ...");
}
}