本文主要介绍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。如果。服务。用户服务。添加()
=====方法执行前======
增加了一个用户
=====方法执行后======
环绕后
空
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。