什么是SpringAOP?
将一些相关的编程方法,独立提取出来,独立实现,然后动态地将代码切入到类的指定方法、指定位置上的编程方式就是AOP(面向切面编程)。
讲解一下AOP中的相关概念
Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。
Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
Target(目标对象):织入 Advice 的目标对象.。
Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程
实例:
接口:
package com.java.test6; /** * @author nidegui * @create 2019-06-23 9:40 */ public interface Student { public void addStudent(String name); }
实现类:
package com.java.test6; /** * @author nidegui * @create 2019-06-23 9:41 */ public class StudentImpl implements Student { @Override public void addStudent(String name) { System.out.println("添加学生"+name); } }
切点增强类:
package com.java.test6; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; /** * @author nidegui * @create 2019-06-23 9:45 */ public class StudentServiceAspect { //前置通知,在方法之前通知 public void before(JoinPoint jp){ System.out.println("类名:"+jp.getTarget().getClass().getName()); System.out.println("方法名:"+jp.getSignature().getName()); System.out.println("开始添加学生:"+jp.getArgs()[0]); System.out.println("开始添加学生"); } //后置通知 public void doAfter(JoinPoint jp){ System.out.println("类名:"+jp.getTarget().getClass().getName()); System.out.println("方法名:"+jp.getSignature().getName()); System.out.println("学生添加完成:"+jp.getArgs()[0]); } //环绕通知 public Object doAround(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("添加学生前"); Object retVal=pjp.proceed(); System.out.println(retVal); System.out.println("添加学生后"); return retVal; } //返回通知 public void doAfterReturning(JoinPoint jp){ System.out.println("返回通知"); } //异常通知 public void doAfterThrowing(JoinPoint jp,Throwable ex){ System.out.println("异常通知"); System.out.println("异常信息:"+ex.getMessage()); } }
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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="studentImpl" class="com.java.test6.StudentImpl"></bean> <bean id="studentAcpect" class="com.java.test6.StudentServiceAspect"></bean> <aop:config> <aop:aspect id="studentAcpect" ref="studentAcpect"> <!--定义一个切点--> <aop:pointcut id="b" expression="execution(* com.java.test6.*.*(..))"></aop:pointcut> <!--定义前置通知--> <aop:before method="before" pointcut-ref="b"></aop:before> <!--后置通知--> <aop:after method="doAfter" pointcut-ref="b"></aop:after> <!--环绕通知--> <aop:around method="doAround" pointcut-ref="b"/> <!--返回通知--> <aop:after-returning method="doAfterReturning" pointcut-ref="b"/> <!--异常通知--> <aop:after-throwing method="doAfterThrowing" pointcut-ref="b" throwing="ex"/> </aop:aspect> </aop:config> </beans>
测试类:
package com.java.test6; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author nidegui * @create 2019-06-22 14:47 */ public class Test { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("beanss.xml"); Student people =(Student) ac.getBean("studentImpl"); people.addStudent("zhangsna"); } }
控制台输出日志: