前言:
本文内容:AOP实现方式一、AOP实现方式二、注解实现AOP
推荐免费Spring5基础教程视频:【狂神说Java】Spring5最新完整教程IDEA版通俗易懂_哔哩哔哩_bilibili
AOP实现方式一
什么是AOP
AOP(Aspect Oriented Programming)即:面向切面编程。是OOP的延续,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型。简单的说他就是把我们程序重复的代码抽取出来,在需要执行的时候使用动态代理技术在不修改源码的基础上,对我们的已有方法进行增强。
AOP在Spring中的作用
提供声明式事务:允许用户自定义切面
- 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关,但是我们需要关注的就是横切关注点。(如:日志,安全,缓存等…)
- 切面(Aspect):横切关注点 被模块化的特殊对象。
- 通知(Advice):切面必须要完成的工作。
- 目标(Target):被通知对象。
- 代理(Proxy):向目标对象应用通知之后创建的对象。
- 切入点(PointCut):切面通知执行的"地点"的定义。
- 连接点(JointPoint):与切入点匹配的执行点。
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5中类型的Advice
通知类型 |
连接点 |
实现接口 |
前置通知 |
方法前 |
org.springframework.aop.MethodBeforeAdvice |
后置通知 |
方法后 |
org.springframework.aop.AfterReturningAdvice |
环绕通知 |
方法前后 |
org.aopalliance.intercept.MethodInterceptor |
异常抛出通知 |
方法抛出异常 |
org.springframework.aop.ThrowsAdvice |
引介通知 |
类中增加新的方法属性 |
org.springframework.aop.IntrductionInterceptor |
使用Spring实现AOP
使用AOP前需要导入一个依赖包
1 2 3 4 5
| <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> </dependency>
|
使用Spring的API接口
UserService.java
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.jokerdig.service;
public interface UserService { public void add(); public void query(); public void update(); public void delete(); }
|
UserServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package com.jokerdig.service;
public class UserServiceImpl implements UserService{ public void add() { System.out.println("添加了一个用户"); }
public void query() { System.out.println("修改了一个用户"); }
public void update() { System.out.println("修改了一个用户"); }
public void delete() { System.out.println("删除了一个用户"); } }
|
Log.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package com.jokerdig.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class Log implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了"); } }
|
AfterLog.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package com.jokerdig.log;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class AfterLog implements AfterReturningAdvice { public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了"+method.getName()+"方法,返回结果为"+returnValue); } }
|
applicationContext.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?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="userService" class="com.jokerdig.service.UserServiceImpl"/> <bean id="log" class="com.jokerdig.log.Log"/> <bean id="afterLog" class="com.jokerdig.log.AfterLog"/>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.jokerdig.service.UserServiceImpl.*(..))"/>
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config> </beans>
|
SpringTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package com.jokerdig.test;
import com.jokerdig.service.UserService; import com.jokerdig.service.UserServiceImpl; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest { @Test public void test6(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService =(UserService) context.getBean("userService");
userService.add(); userService.query(); } }
|
运行结果
1 2 3 4 5 6 7 8
| com.jokerdig.service.UserServiceImpl的add被执行了 添加了一个用户 执行了add方法,返回结果为null com.jokerdig.service.UserServiceImpl的query被执行了 修改了一个用户 执行了query方法,返回结果为null
Process finished with exit code 0
|
AOP实现方式二
使用自定义类实现AOP(切面)
DiyPointCut.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.jokerdig.diy;
public class DiyPointCut {
public void before(){ System.out.println("=============方法执行前=============="); } public void after(){ System.out.println("=============方法执行后=============="); } }
|
applicationContext1.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?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="userService" class="com.jokerdig.service.UserServiceImpl"/> <bean id="log" class="com.jokerdig.log.Log"/> <bean id="afterLog" class="com.jokerdig.log.AfterLog"/>
<bean id="diy" class="com.jokerdig.diy.DiyPointCut"/> <aop:config>
<aop:aspect ref="diy">
<aop:pointcut id="point" expression="execution(* com.jokerdig.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config> </beans>
|
SpringTest.java
1 2 3 4 5 6 7 8 9 10
| @Test public void test7(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext1.xml");
UserService userService =(UserService) context.getBean("userService");
userService.add(); userService.query(); }
|
运行结果
1 2 3 4 5 6 7 8
| =============方法执行前============== 添加了一个用户 =============方法执行后============== =============方法执行前============== 修改了一个用户 =============方法执行后==============
Process finished with exit code 0
|
注解实现AOP
使用注解实现AOP
AnnotationPointCut.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| package com.jokerdig.diy;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before;
@Aspect public class AnnotationPointCut {
@Before("execution(* com.jokerdig.service.UserServiceImpl.*(..))") public void before(){ System.out.println("========方法执行前=========="); }
@After("execution(* com.jokerdig.service.UserServiceImpl.*(..))") public void after(){ System.out.println("========方法执行后=========="); }
@Around("execution(* com.jokerdig.service.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint jp) throws Throwable { System.out.println("======环绕前=======");
Object proceed = jp.proceed();
System.out.println("======环绕后======="); } }
|
applicationContext2.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?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="userService" class="com.jokerdig.service.UserServiceImpl"/> <bean id="log" class="com.jokerdig.log.Log"/> <bean id="afterLog" class="com.jokerdig.log.AfterLog"/>
<bean id="annocationPointCut" class="com.jokerdig.diy.AnnotationPointCut"/>
<aop:aspectj-autoproxy/> </beans>
|
SpringTest.java
1 2 3 4 5 6 7 8 9 10
| @Test public void test8(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext2.xml");
UserService userService =(UserService) context.getBean("userService");
userService.add(); userService.query(); }
|
运行结果
1 2 3 4 5 6 7 8 9 10 11 12
| ======环绕前======= ========方法执行前========== 添加了一个用户 ========方法执行后========== ======环绕后======= ======环绕前======= ========方法执行前========== 修改了一个用户 ========方法执行后========== ======环绕后=======
Process finished with exit code 0
|
注意:这里环绕后
在方法执行后
的后面,是Spring新版的新特性
之前的版本中 环绕后
在方法执行后
的前面