本文主要介绍Spring AOP的面向方面编程原理和方法的详细讲解,通过实例代码详细介绍,对大家的学习或工作有一定的参考价值,有需要的朋友可以参考一下。
1. 什么是AOP
AOP (Aspect Oriented Programming)的意思是:面向方面编程(Aspect-oriented programming ),是一种通过预编译和运行时动态代理,在不修改源代码的情况下,动态统一地向程序添加功能的技术。可以理解为动态代理。它是Spring框架中的一个重要内容。AOP可以用来隔离业务逻辑的各个部分,降低业务逻辑各个部分之间的耦合度,提高程序的复用性,提高开发效率。
2.春季AOP
春季AOP的作用
提供声明性事务;允许用户自定义切面。
.AOP的基本概念
横切关注点:跨越应用程序多个模块的方法或功能。也就是说,它与我们的业务逻辑无关,但需要我们注意的部分是横切关注点。例如日志、安全性、缓存、事务等。
方面:横切关注点被模块化的特殊对象。它通常是一个可以定义切入点和通知的类。
编织:将方面连接到其他应用程序类型或对象,并创建一个通知对象。这些可以在编译时、类加载时和运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成编织。
建议:AOP对特定切入点进行的增强处理是切入点必须完成的工作,也是类中的一个方法。
目标:被通知的对象。
AOP(Agent):AOP框架创建的对象,Agent是目标对象的增强。Spring中的AOP agent可以是JDK动态agent,也可以是CGLIB agent,前者基于接口,后者基于子类。
连接点:程序执行过程中的一个显式点,通常是方法的调用。
切入点:带有通知的连接点,以及匹配切入点的执行点。
使用Spring实现Aop
先决条件
使用AOP编织,您需要导入一个依赖包。
属国
groupIdorg.aspectj/groupId
artifactIdaspectjweaver/artifactId
版本1 . 9 . 5/版本
/依赖关系
实现Aop的三种方式
方式一:通过 Spring API 实现【主要是springAPI接口实现】
首先,编写业务接口和实现类。
公共接口用户服务{
public void add();
public void delete();
公共void update();
public void搜索();
}
公共类UserServiceImpl实现UserService{
公共void add() {
System.out.println(添加了用户);
}
公共void delete() {
System.out.println(删除了一个用户);
}
公共void更新(){
System.out.println(“更新了一个用户”);
}
公共void select() {
System.out.println(查询了用户);
}
}
然后写增强类,这里有两个:增强前的Log和增强后的AfterLog。
导入org . spring framework . AOP . method before advice;
导入Java . lang . reflect . method;
公共类日志实现MethodBeforeAdvice {
//方法:要执行的目标对象的方法。
//args: parameter
//target:目标对象
public void before(Method method,Object[] args,Object target)抛出Throwable {
system . out . println( method . getname() of target . getclass())。已执行“getname()”);
}
}
导入org . spring framework . AOP . afterreturningadvice;
导入Java . lang . reflect . method;
公共类AfterLog实现AfterReturningAdvice {
//returnValue;返回值
public void after returning(Object return value,Method method,Object[] args,Object target)抛出Throwable {
执行了system . out . println( method . getname()方法,返回结果为: return value );
}
}
最后在Spring的文件中注册(applicationContext.xml),并实现AOP切入,注意导入约束。
?xml版本=1.0 编码=UTF-8 ?
beans xmlns= http://www . spring framework . org/schema/beans
xmlns:xsi= http://www . w3 . org/2001/XML schema-instance
xmlns:AOP= http://www . spring framework . org/schema/AOP
xsi:架构位置= http://www。spring框架。组织/模式/bean
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
!-注册豆子-
bean id= userService class= com。如果。服务。userserviceimpl /
bean id= log class= com。如果。日志。日志/
bean id= after log class= com。如果。日志。日志后/
!-方式一:使用原生Spring API接口-
!-配置aop:需要导入面向切面编程(面向方面的编程的缩写)的约束-
aop:配置
!-切入点:表达式:表达式,执行(要执行的位置!* * * * *) -
AOP:pointcut id= pointcut expression= execution(* com。如果。服务。userserviceimpl。*(.))/
!-执行环绕;建议-参考执行方法。切入点引用切入点-
aop:顾问建议-ref= log 切入点-ref= pointcut /
aop:顾问建议-ref= after log 切入点-ref=切入点/
/aop:config
/豆子
进行测试:
导入com。如果。服务。用户服务;
导入org。朱尼特。测试;
导入org。spring框架。语境。应用程序上下文;
导入组织。spring框架。语境。支持。classpathmlaplicationcontext
公共类我的测试{
@测试
公共无效测试(){
application context context=new ClassPathXmlApplicationContext( application context。XML’);
用户服务用户服务1=(用户服务)上下文。获取bean(“用户服务”);
用户服务UserService=(UserService)上下文。获取bean( user service );
用户服务。add();
}
}
运行结果:
com.lf.service.UserServiceImpl的增加被执行了
增加了一个用户
执行了增加方法,返回结果为:空
方式二:自定义类实现AOP【主要是切面定义】
目标业务类不变,还是方式一中的用户服务冲动
写入一个切入类
公共类DIY切入点{
之前的公共空的
System.out.println(========方法执行前=========);
}
(){
System.out.println(========方法执行后=========);
}
}
在春天中配置(应用程序上下文。xml)
?可扩展标记语言版本=1.0 编码=UTF八号?
豆子xmlns= http://www。spring框架。组织/架构/bean
xmlns:xsi= http://。w3。 org/2001/XML架构-实例
xmlns:AOP= http://。spring框架。组织/架构/AOP
xsi:架构位置= http://www。spring框架。组织/模式/bean
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
!-注册豆子-
bean id= userService class= com。如果。服务。userserviceimpl /
bean id= log class= com。如果。日志。日志/
bean id= after log class= com。如果。日志。日志后/
!-方式二:自定义类-
bean id= DIY class= com。如果。DIY。DIY切入点/
aop:配置
!-自定义切面,参考要引用的类-
aop:aspect ref=diy
!-切入点-
AOP:切入点id= point 表达式= execution(* com。如果。服务。userserviceimpl。*(.))/
!-通知-
AOP:before method= before pointcut-ref= point /
AOP:after method= after pointcut-ref= point /
/aop:方面
/aop:config
/豆子
在上面的MyTest.java中测试,得到结果:
========方法执行前=========
增加了一个用户
========方法执行后=========
方式三:使用注解实现【多用】
编写一个注解实现的增强类
包com。如果。DIY
导入org。AspectJ。郎。proceedingjoinpoint
导入org。AspectJ。郎。签名;
导入org。AspectJ。郎。注释。之后;
导入org。AspectJ。郎。注释。周围;
导入org。AspectJ。郎。注释。方面;
导入org。AspectJ。郎。注释。之前;
@Aspect //标注这个类是一个切面
公共类注释切入点{
@ Before(执行(* com。如果。服务。userserviceimpl。*(.)))
之前的公共空的
System.out.println(=====方法执行前======);
}
@ After(执行(* com。如果。服务。userserviceimpl。*(.)))
(){
System.out.println(=====方法执行后======);
}
//在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点;
@ Around(执行(* com。如果。服务。userserviceimpl。*(.)))
公共void around(proceeding join point jp)Throwable {
System.out.println(环绕前);
签名签名=jp。获取签名();//获得签名
System.out.println(签名:签名);
对象进行=jp。proceed();//执行方法
System.out.println(环绕后);
System.out.println(继续);
}
}
在春天配置文件中,注册豆子,并增加支持注解的配置
?可扩展标记语言版本=1.0 编码=UTF八号?
豆子xmlns= http://www。spring框架。组织/架构/bean
xmlns:xsi= http://。w3。 org/2001/XML架构-实例
xmlns:AOP= http://。spring框架。组织/架构/AOP
xsi:架构位置= http://www。spring框架。组织/模式/bean
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
!-注册豆子-
bean id= userService class= com。如果。服务。userserviceimpl /
bean id= log class= com。如果。日志。日志/
bean id= after log class= com。如果。日志。日志后/
!-方式三-
bean id= annotationPointCut class= com。如果。DIY。annotationPointCut /
!-开启注解支持!JDK(默认proxy-target-class= false )cglib(proxy-target-class= true )-
aop:aspectj-autoproxy/
/豆子
在MyTest.java中测试
导入com。如果。服务。用户服务;
导入org。朱尼特。测试;
导入org。spring框架。语境。应用程序上下文;
导入组织。spring框架。语境。支持。classpathmlaplicationcontext
公共类我的测试{
@测试
公共无效测试(){
application context context=new ClassPathXmlApplicationContext( application context。XML’);
用户服务UserService=(UserService)上下文。获取bean( user service );
用户服务。add();
}
}
得到结果:
环绕前
签名:void com。如果。服务。用户服务。添加()
=====方法执行前======
增加了一个用户
=====方法执行后======
环绕后
空
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。