AOP入门

AOP(AspectOrientedProgramming)是一种编程技术,用于减少代码重复,提高可复用性和开发效率。它通过预编译和动态代理在不修改原有逻辑的情况下插入代码。AOP的核心概念包括切面、切入点、连接点、目标对象和Advice。文章介绍了三种实现AOP的方式:通过SpringAPI、自定义类和注解实现,并提供了示例代码。

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

什么是AOP

AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译和运行期间动态代理来实现程序功能的统一维护的技术,是OOP的一种延伸,利用AOP可以对业务逻辑的各个部分进行隔离,从而使业务逻辑各部分之间的耦合度降低,提高程序的可复用性,同时提高了开发效率。

一句话总结:AOP动态的将代码在不改变原有逻辑情况下切入到类的指定方法。

AOP的作用

在原来我们实现业务时,如果业务一和业务二同时需要增加业务内容(业务三),如果我们分别在两个业务中分别增加业务三,不仅会使代码重复度高,而且违背了开闭原则(对扩展开放,对修改关闭)。为了既不增加代码重复度,又不违背开闭原则,提出了AOP。

在这里插入图片描述
我们将切入到指定方法的代码片称为切面(Aspect);将切入到的哪些类,哪些方法称为切入点(point cut)

其他有关AOP的术语

连接点(joint point)

目标对象(Target)

Proxy

Advice

AOP的实现

方式一(通过spring API实现)

第一步,导包

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

第二步,编写业务接口和实现类

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void search();
}
package com.example.Service;

public class UserServiceImp implements UserService{
    @Override
    public void add() {
        System.out.println("add...");
    }

    @Override
    public void delete() {
        System.out.println("delete...");
    }

    @Override
    public void update() {
        System.out.println("update");
    }

    @Override
    public void search() {
        System.out.println("search...");
    }
}

第三步,编写Aspect类,该方式的实现是通过实现Advice的接口
这里只编写了前置和后置的Aspect

前置方法

package com.example.Log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class BeforeLog implements MethodBeforeAdvice {

    @Override
    //method:要执行的目标的方法
    //args:被调用的方法的参数
    //target:目标对象
    public void before(Method method, Object[] args, Object target) throws Throwable {
        //这里写在切片点之前的增强方法
        System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行");

    }
}

后置方法

public class AfterLog implements AfterReturningAdvice {
    @Override
    //returnValue 返回值
    //method 被调用的方法
    //objects 被调用的方法的对象的参数
    //target 被调用的目标对象
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        //此处写切片点之后的增强方法
        System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行,返回值:"+ returnValue);

    }
}

spring配置文件

<?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.example.Service.UserServiceImp"></bean>
    <bean id="beforeLog" class="com.example.Log.BeforeLog"></bean>
    <bean id="afterLog" class="com.example.Log.AfterLog"></bean>

<!--    aop方式一-->



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

    </aop:config>
</beans>


测试

public class Test {
    @org.junit.Test
    public void test(){
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserService userService = context.getBean("userService",UserService.class);
    userService.add();
    }
}

在这里插入图片描述

方式二(自定义类实现Aspect)

业务层不变(略)

自定义Aspect类

public class DiyPointCut {

    public void before(){
        System.out.println("程序执行前=====================");
    }
    
    public void after(){
        System.out.println("程序执行后====================");
    }
}

spring配置文件

<?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.example.Service.UserServiceImp"></bean>
    <bean id="diyPointCut" class="com.example.Diy.DiyPointCut"></bean>


<!--aop方式二-->
    <aop:config>
<!--        切面-->
        <aop:aspect ref="diyPointCut" >
<!--            切入点-->
            <aop:pointcut id="pointCut" expression="execution(* com.example.Service.UserServiceImp.*(..))"/>
            <aop:before method="before" pointcut-ref="pointCut"></aop:before>
            <aop:after method="after" pointcut-ref="pointCut"></aop:after>
        </aop:aspect>
    </aop:config>

</beans>

测试

import com.example.Service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    @org.junit.Test
    public void test(){
      ApplicationContext context =  new ClassPathXmlApplicationContext("applicationContext.xml");
      UserService userService = context.getBean("userService",UserService.class);
      userService.add();
    }
}

在这里插入图片描述

方式三(注解实现Aspect)

业务层不变(略)

自定义Aspect类

//声明这是一个aop切片
@Aspect
public class DiyPointCut2 {
    @Pointcut(value="execution(* com.example.Service.UserServiceImp.*(..))")
    public void pointcut(){}

    @Before(value="pointcut()")
    public void before(){
        System.out.println("程序执行前================");
    }

    @After(value="pointcut()")
    public void after(){
        System.out.println("程序执行后==============================");
    }

    @Around(value="pointcut()")
    public void around(ProceedingJoinPoint jp){
        System.out.println("环绕前");
//        System.out.println("签名:"+jp.getSignature());
        //执行目标方法proceed
        Object proceed = null;
        try {
            proceed = jp.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("环绕后");
        System.out.println(proceed);
    }
}

spring配置文件

<?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.example.Service.UserServiceImp"></bean>
    <bean id="diyPointCut" class="com.example.Diy.DiyPointCut"></bean>

<!--    方式三,使用注解-->
<!--    注册bean-->
<bean id="pointCut2" class="com.example.Diy.DiyPointCut2"></bean>
<!--    开启注解实现aop-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

测试

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值