Spring核心概念之AOP详解

本文详细介绍了Spring中的AOP概念,包括AOP的作用、名词解释,以及三种不同的实现方式:基于Spring API、自定义类和注解实现。重点强调了注解实现作为推荐方法,并通过实例展示了AOP如何提升代码复用性和领域业务的纯粹性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

什么是AOP

Aop在Spring中的作用

基于SpringApi实现AOP

基于自定义类来实现Aop

基于注解实现Aop(推荐)


 

什么是AOP

 

AOP(Aspect Oriented Programming)意为:面向切面编程。作用是在不影响原业务类的基础上实现了增强

 

 

Aop在Spring中的作用

 

 需要了解的名词

  • 横切关注点即某一个要加的功能。跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 ....

  • 切面(ASPECT):这个功能的类名叫什么。横切关注点 被模块化 的特殊对象。即,它是一个类。

  • 通知(Advice):类中的方法。切面必须要完成的工作。即,它是类中的一个方法。

  • 目标(Target):被通知对象

  • 代理(Proxy):生成的代理类。向目标对象应用通知之后创建的对象。

  • 切入点(PointCut):在哪个地方执行。切面通知 执行的 “地点”的定义。

  • 连接点(JointPoint):在哪个地方执行。与切入点匹配的执行点。

AOP中内置了5种通知类型,即五种方法类型

 

 

基于SpringApi实现AOP

 

1.导包 

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjweaver</artifactId>
   <version>1.9.4</version>
</dependency>

2.写Service接口

public interface UserService {

    public void add();

    public void delete();

    public void update();

    public void search();

}

3.Service的实现类

public class UserServiceImpl implements UserService{

   @Override
   public void add() {
       System.out.println("增加用户");
  }

   @Override
   public void delete() {
       System.out.println("删除用户");
  }

   @Override
   public void update() {
       System.out.println("更新用户");
  }

   @Override
   public void search() {
       System.out.println("查询用户");
  }
}

 4.然后我们新建一个切面,也就是要增加的具体功能类

public class Log implements MethodBeforeAdvice {

   //method : 要执行的目标对象的方法
   //objects : 被调用的方法的参数
   //Object : 目标对象
   @Override
   public void before(Method method, Object[] objects, Object o) throws Throwable {
       System.out.println( o.getClass().getName() + "的" + method.getName() + "方法被执行了");
  }
}

5.再来一个切面

public class AfterLog implements AfterReturningAdvice {
   //returnValue 返回值
   //method被调用的方法
   //args 被调用的方法的对象的参数
   //target 被调用的目标对象
   @Override
   public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
       System.out.println("执行了" + target.getClass().getName()
       +"的"+method.getName()+"方法,"
       +"返回值:"+returnValue);
  }
}

6.新建一个applicationContext.xml文件负责去Spring的文件中注册 , 并实现aop切入实现 , 注意导入约束 .

<?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-->
    <bean id="userService" class="com.lt.Demo.UserServiceImpl"/>
    <bean id="log" class="com.lt.Demo.Log"/>
    <bean id="afterLog" class="com.lt.Demo.AfterLog"/>

    <!--aop的配置-->
    <aop:config>
        <!--切入点 expression:表达式匹配要执行的方法-->
        <aop:pointcut id="pointcut" expression="execution(* com.lt.Demo.UserServiceImpl.*(..))"/>
        <!--执行环绕; advice-ref执行方法 . pointcut-ref切入点-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>

</beans>

测试

public class MyTest {
   @Test
   public void test(){
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
       UserService userService = (UserService) context.getBean("userService");
       userService.search();
  }
}

Spring的Aop就是将公共的业务 (日志 , 安全等) 和领域业务结合起来 , 当执行领域业务时 , 将会把公共业务加进来 . 实现公共业务的重复利用 . 领域业务更纯粹 , 程序猿专注领域业务 , 其本质还是动态代理 .

 

 

基于自定义类来实现Aop

 

1.我们自己定义一个切入类

public class DiyPointcut {

   public void before(){
       System.out.println("---------方法执行前---------");
  }
   public void after(){
       System.out.println("---------方法执行后---------");
  }
   
}

2.去Spring中配置

    <bean id="diy" class="com.lt.Demo.DiyPointcut"/>

    <!--aop的配置-->
    <aop:config>
        <aop:aspect ref="diy">
            <aop:pointcut id="diyPonitcut" expression="execution(* com.lt.Demo.UserServiceImpl.*(..))"/>
            <aop:before pointcut-ref="diyPonitcut" method="before"/>
            <aop:after pointcut-ref="diyPonitcut" method="after"/>
        </aop:aspect>
    </aop:config>

3.测试

   @Test
   public void test(){
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
       UserService userService = (UserService) context.getBean("userService");
       userService.search();
  }

 

 

基于注解实现Aop(推荐)

 

1.编写一个注解实现增强类

package com.lt.Demo;

import org.aspectj.lang.ProceedingJoinPoint;
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.lt.Demo.UserServiceImpl.*(..))")
   public void before(){
       System.out.println("---------方法执行前---------");
  }

   @After("execution(* com.lt.Demo.UserServiceImpl.*(..))")
   public void after(){
       System.out.println("---------方法执行后---------");
  }

   @Around("execution(* com.lt.Demo.UserServiceImpl.*(..))")
   public void around(ProceedingJoinPoint jp) throws Throwable {
       System.out.println("环绕前");
       System.out.println("签名:"+jp.getSignature());
       //执行目标方法proceed
       Object proceed = jp.proceed();
       System.out.println("环绕后");
       System.out.println(proceed);
  }
}

 

2.在Spring配置文件中,注册bean,并增加支持注解的配置

    <!--第三种方式:注解实现-->
    <bean id="annotationPointcut" class="com.lt.Demo.AnnotationPointcut"/>
    <aop:aspectj-autoproxy/>

 

<aop:aspectj-autoproxy />有一个proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy  poxy-target-class="true"/>时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值