2022.5.30 AOP
11、AOP
11.1、什么是AOP
AOP (Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
11.2、Aop在Spring中的作用
提供声明式事务;允许用户自定义切面
-
横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等.....
-
切面(ASPECT)︰横切关注点被模块化的特殊对象。即,它是一个类。
-
通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
-
目标(Target)∶被通知对象。
-
代理(Proxy)︰向目标对象应用通知之后创建的对象。
-
切入点(PointCut) :切面通知执行的“地点"的定义。
-
连接点(JointPoint) :与切入点匹配的执行点。
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:
即Aop在不改变原有代码的情况下,去增加新的功能.
11.3、使用Spring实现Aop
【重点】使用AOP织入,需要导入一个依赖包!
1 <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> 2 <dependency> 3 <groupId>org.aspectj</groupId> 4 <artifactId>aspectjweaver</artifactId> 5 <version>1.9.8</version> 6 </dependency>
方式一︰使用Spring的API接口
xml需要配置aop约束
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 5 约束 6 xmlns:aop="http://www.springframework.org/schema/aop" 7 8 xsi:schemaLocation="http://www.springframework.org/schema/beans 9 https://www.springframework.org/schema/beans/spring-beans.xsd 10 11 约束 12 http://www.springframework.org/schema/aop 13 https://www.springframework.org/schema/aop/spring-aop.xsd"> 14 15 </beans>
练习:
UserService
1 package com.xing.service; 2 3 public interface UserService { 4 void add(); 5 void delete(); 6 void update(); 7 void select(); 8 9 }
UserServiceImpl
1 package com.xing.service; 2 3 public class UserServiceImpl implements UserService{ 4 @Override 5 public void add() { 6 System.out.println("增加一个用户"); 7 } 8 9 @Override 10 public void delete() { 11 System.out.println("删除一个用户"); 12 } 13 14 @Override 15 public void update() { 16 System.out.println("修改一个用户"); 17 } 18 19 @Override 20 public void select() { 21 System.out.println("查询一个用户"); 22 } 23 }
Log
1 package com.xing.log; 2 3 import org.springframework.aop.MethodBeforeAdvice; 4 5 import java.lang.reflect.Method; 6 7 //MethodBeforeAdvice在插入的方法前执行 8 public class Log implements MethodBeforeAdvice { 9 10 // method:要执行的目标对象的方法 11 //args:参数 12 //target: 目标对象 13 @Override 14 public void before(Method method, Object[] args, Object target) throws Throwable { 15 System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了"); 16 } 17 }
AfterLog
1 package com.xing.log; 2 3 import org.springframework.aop.AfterReturningAdvice; 4 5 import java.lang.reflect.Method; 6 7 // AfterReturningAdvice再插入的方法后执行 8 public class AfterLog implements AfterReturningAdvice { 9 10 @Override 11 //返回值 12 public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { 13 System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnValue); 14 } 15 }
applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 5 xmlns:aop="http://www.springframework.org/schema/aop" 6 7 xsi:schemaLocation="http://www.springframework.org/schema/beans 8 https://www.springframework.org/schema/beans/spring-beans.xsd 9 10 http://www.springframework.org/schema/aop 11 https://www.springframework.org/schema/aop/spring-aop.xsd"> 12 13 <bean id="userService" class="com.xing.service.UserServiceImpl"/> 14 <bean id="log" class="com.xing.log.Log"/> 15 <bean id="afterlog" class="com.xing.log.AfterLog"/> 16 <!-- 配置aop:需要导入aop约束--> 17 <aop:config> 18 19 <!--切入点: expression:表达式,execution() ·· *可以是任意文件类型 要插入方法的文件路径 .*给这个文件下的所有方法都插入 每个方法都有不同的参数(..)代表所有参数类型--> 20 <aop:pointcut id="pointcut" expression="execution(* com.xing.service.UserServiceImpl.*(..))"/> 21 22 <!--执行环绕增加 把log(bean的id)代表的类切入到 pointcut(aop的id)切点处--> 23 <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> 24 <aop:advisor advice-ref="afterlog" pointcut-ref="pointcut"/> 25 26 </aop:config> 27 </beans>
test
1 import com.xing.service.UserService; 2 import org.springframework.context.ApplicationContext; 3 import org.springframework.context.support.ClassPathXmlApplicationContext; 4 5 public class MyTest { 6 public static void main(String[] args) { 7 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 8 //动态代理代理的是接口 9 UserService userService = (UserService) context.getBean("userService"); 10 userService.add(); 11 System.out.println("=============================="); 12 userService.delete(); 13 } 14 }
方式二:自定义类实现
DiyPointCut
1 package com.xing.diy; 2 3 //自己定义一个类,类中设置切入点加入的方法 4 public class DiyPointCut { 5 public void before() { 6 System.out.println("方法执行前加入的方法"); 7 } 8 9 public void after() { 10 System.out.println("方法执行后加入的方法"); 11 } 12 }
applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 5 xmlns:aop="http://www.springframework.org/schema/aop" 6 7 xsi:schemaLocation="http://www.springframework.org/schema/beans 8 https://www.springframework.org/schema/beans/spring-beans.xsd 9 10 http://www.springframework.org/schema/aop 11 https://www.springframework.org/schema/aop/spring-aop.xsd"> 12 13 <bean id="userService" class="com.xing.service.UserServiceImpl"/> 14 <bean id="log" class="com.xing.log.Log"/> 15 <bean id="afterlog" class="com.xing.log.AfterLog"/> 16 17 <bean id="diy" class="com.xing.diy.DiyPointCut"/> 18 19 <aop:config> 20 <!--将diy类标注为切面,ref要引用的类(bean的id所代表的类)--> 21 <aop:aspect ref="diy"> 22 <!--要切入的点--> 23 <aop:pointcut id="point" expression="execution(* com.xing.service.UserServiceImpl.*(..))"/> 24 25 26 <!--通知--> 27 <!--切入点前插入的方法 自已定义diy中的方法名 要插入的切入点(切入点可能有多个)--> 28 <aop:before method="before" pointcut-ref="point"/> 29 <!--切入点后插入的方法--> 30 <aop:after method="after" pointcut-ref="point"/> 31 </aop:aspect> 32 </aop:config> 33 34 </beans>
test
1 import com.xing.service.UserService; 2 import org.springframework.context.ApplicationContext; 3 import org.springframework.context.support.ClassPathXmlApplicationContext; 4 5 public class MyTest { 6 public static void main(String[] args) { 7 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 8 //动态代理代理的是接口 9 UserService userService = (UserService) context.getBean("userService"); 10 userService.add(); 11 System.out.println("=============================="); 12 userService.delete(); 13 } 14 }
方式三:使用注解实现
AnnotationPointCut
1 package com.xing.diy; 2 3 import org.aspectj.lang.annotation.After; 4 import org.aspectj.lang.annotation.Around; 5 import org.aspectj.lang.annotation.Aspect; 6 import org.aspectj.lang.annotation.Before; 7 8 @Aspect //标注为一个切面 9 public class AnnotationPointCut { 10 //在切入点之前执行 参数为切入点 11 @Before("execution(* com.xing.service.UserServiceImpl.*(..))") 12 public void before() { 13 System.out.println("方法执行前加入的方法"); 14 } 15 16 @After("execution(* com.xing.service.UserServiceImpl.*(..))") 17 public void after() { 18 System.out.println("方法执行后加入的方法"); 19 } 20 21 22 }
applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 5 xmlns:aop="http://www.springframework.org/schema/aop" 6 7 xsi:schemaLocation="http://www.springframework.org/schema/beans 8 https://www.springframework.org/schema/beans/spring-beans.xsd 9 10 http://www.springframework.org/schema/aop 11 https://www.springframework.org/schema/aop/spring-aop.xsd"> 12 13 <bean id="userService" class="com.xing.service.UserServiceImpl"/> 14 <bean id="log" class="com.xing.log.Log"/> 15 <bean id="afterlog" class="com.xing.log.AfterLog"/> 16 17 18 <bean id="apc" class="com.xing.diy.AnnotationPointCut"/> 19 <!--开启注解支持--> 20 <aop:aspectj-autoproxy/> 21 22 </beans>
test
1 import com.xing.service.UserService; 2 import org.springframework.context.ApplicationContext; 3 import org.springframework.context.support.ClassPathXmlApplicationContext; 4 5 public class MyTest { 6 public static void main(String[] args) { 7 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 8 //动态代理代理的是接口 9 UserService userService = (UserService) context.getBean("userService"); 10 userService.add(); 11 System.out.println("=============================="); 12 userService.delete(); 13 } 14 }
分类:
spring
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· 地球OL攻略 —— 某应届生求职总结