计算机系统应用教程网站

网站首页 > 技术文章 正文

实践:Spring AOP的注解和XML配置使用教程

btikc 2024-09-16 12:54:24 技术文章 24 ℃ 0 评论

分享自己在Java方面的所思所想,希望你看完之后能有更多更深入的了解,欢迎关注(VX同号)

在之前已经从ProxyFactory和ProxyFactoryBean这两个最基础的类中学习和了解Spring AOP,具体文章可见 看完或许你会重新认识和理解Spring AOP的工作原理 ,现在就来具体从XML配置和注解配置两种方法具体实践一下。

AOP 概念了解

AOP(Aspect Oriented Programming)面向切面编程,是针对面向对象编程的一种补充,同时也是spring中第二个最核心的功能,例如可以进行权限认证,日志输出等,可以无侵入的对原来的功能进行切面加入自定义的非业务功能。

  • 切面(AspectJ):对横切关注点的抽象
  • 连接点(Joinpoint):被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
  • 通知(Advice):AOP框架在特定的切入点执行的增强处理,分为前置、后置、异常、最终、环绕五种情况
  • 切入点(Pointcut):需要拦截的点
  • 引入:将方法或字段添加到被处理的类中。Spring允许引入新的接口到任何被处理的对象。例如,你可以使用一个引入,使任何对象实现IsModified接口,以此来简化缓存
  • 目标对象:被AOP框架进行增强处理的对象,也被称为被增强的对象
  • AOP代理:AOP框架创建的对象,简单的说,代理就是对目标对象的加强。Spring中的AOP代理可以是JDK动态代理,也可以是CGLIB代理
  • 织入(Weaving):将增强处理添加到目标对象中,并创建一个被增强的对象的过程。

在spring中AOP代理对象依旧是由IOC容器管理着,在具体代理生成中可以由java动态代理生成也可以由cglib字节码增强完成,具体运行中会根据具体情况选择合适的代码生成方式。如果是接口,则只会使用动态代理生成

在了解完AOP的基础知识后,介绍AOP的两种使用方法,XML配置和注解

XML 配置

<bean id="people" class="com.demo.Aop.People" />
<bean id="peopleAop" class="com.demo.Aop.PeopleAop" />
<aop:config>
 <aop:pointcut id="pc" expression="execution(* com.demo.Aop.*.*(..))" />
 <aop:aspect ref="peopleAop">
 <aop:after method="after" pointcut-ref="pc" />
 <aop:before method="before" pointcut-ref="pc" />
 <aop:around method="around" pointcut-ref="pc" />
 <aop:after-returning method="afterReturn" pointcut-ref="pc" />
 <aop:after-throwing method="excep" pointcut-ref="pc" />
 </aop:aspect>
</aop:config>
public class PeopleAop {
 public void before(){
 System.out.println("before");
 }
 public void after(){
 System.out.println("after");
 }
 public Object around(ProceedingJoinPoint pj){
 System.out.println("around before");
 Object obj = null;
 try {
 obj = pj.proceed();
 } catch (Throwable throwable) {
 }
 System.out.println("around after");
 return obj;
 }
 public void afterReturn(){
 System.out.println("after return");
 }
 public void excep(){
 System.out.println("error!!!!");
 }
}
public class People {
 public void say() {
 System.out.println("chinese");
 }
}

最后的执行结果

看图得出先后顺序是before、around、after、after return。但是xml配置的执行顺序就真的是这样的么?

当我把上面xml配置的before和around换一个位置之后输出到结果

结果发生了变化,成为了around、before、after、after return

注解

<bean class="com.demo.Aop.AnimalImpl" id="animal" />
<bean class="com.demo.Aop.AnimalAop" id="animalAop" />
<!-- 上面两个bean 只是为了便于说明代码,也可以使用component-scan 配合相关注解完成-->
<aop:aspectj-autoproxy />
<!-- AOP注解核心配置,会生成相关的代理类-->
// 接口类
public interface Animal {
 void sleep(String name);
}
// 实现类
public class AnimalImpl implements Animal {
 public AnimalImpl() {
 System.out.println("init");
 }
 public void sleep(String name) {
 System.out.println(name + " sleep");
 }
}
// 切面类
public class AnimalAop {
 @Pointcut("execution(* com.demo.Aop.*.*(..))")
 public void pointCut(){}
 // 定义一个切点,会选择com.demo.Aop下面所有的类
 @Around("pointCut() && args(name)")
 public Object around(ProceedingJoinPoint pj, String name){
 // 定义为around注解,添加了切点,并且同时加上了参数
 Object obj = null;
 System.out.println(name + " around before");
 try {
 obj = pj.proceed();
 } catch (Throwable throwable) {
 throwable.printStackTrace();
 }
 System.out.println(name + " around after");
 return obj;
 }
 @Before("pointCut() && args(name)")
 public void before(String name){
 System.out.println(name + " animal before");
 }
 @After("execution(* com.demo.Aop.*.*(..))")
 public void after(){
 // 这个直接使用了execution,而没有使用已经定义好的切点
 System.out.println("animal after");
 }
 
}

执行结果

在原本的实现类实现之后,执行的先后顺序为around、before、after、after return

不过这里是没有XML注解的那种先后执行顺序,所有的执行顺序都是由spring自身决定的

在当前的demo中可能注意到了,所使用的AnimalImpl是继承自Animal接口的,如果改成没有接口的情况呢?


很明显 在使用接口的时候,spring会使用java的动态代理实现,否则会使用cglib实现代理功能。

原创推荐

手写RPC框架(5)重写服务治理和引入netty,猜猜1000线程情况如何

「面试」new String("abc")和"abc"有什么区别?反编译看看原理吧

「源码」SpringBoot启动原理,你是否清楚?

「深入」HashMap再学习,相比Java7,Java8源码你了解多少

「面试」LRU了解么?看看LinkedHashMap如何实现LRU算法

用BeanPostProcessor和BeanFactoryPostProcessor修改bean的属性

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表