Spring-AOP-春天的故事3

本文详细介绍了面向切面编程(AOP)的概念及其与面向对象编程(OOP)的区别,阐述了AOP如何通过模块化横切关注点来提高代码的可维护性和可重用性。同时,列举了AOP在实际开发中的应用场景,并通过一个具体示例展示了如何在Spring框架下实现AOP。

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

简介

AOP(Aspect-Oriented Programming):面向切面编程,AOP的主要编程对象是切面,而切面模块化横切关注点.

AOP可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

而AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。

实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
好处

-每个事物逻辑位于一个位置,代码不分散,便于维护升级
-业务模板更简洁,只包含核心业务代码。

使用场景

名称解释
Authentication权限
Caching缓存
Context passing内容传递
Error handling错误处理
Lazy loading懒加载
Debugging调试
logging, tracing, profiling and monitoring记录跟踪 优化 校准
Performance optimization性能优化
Persistence持久化
Resource pooling资源池
Synchronization同步
Transactions事务

概念

切面 Aspect:横切关注点被模块化的特殊对象
**通知**Advice:切面必须完成的工作
**目标**Target:被通知的对象
**代理**Proxy:向目标对象 应用通知之后创建的对象
**连接点J**oinpoint:程序执行的某个特定位置
切点*pointcut:每个类都拥有多个连接点,即连接点是程序类中客观存在的事物,AOP通过切点定位到特定的连接点。类比:连接点相当于数据库中的记录,切点相当于查询条件。*指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上

入门例子,前置通知

场景:在每次调用add,multiply方法前做某些操作,类似日志记录。

package com.test.aop;

public interface Calculation {
    int add(int x,int y);
    int multiply(int x,int y);
}
package com.test.aop;

import org.springframework.stereotype.Component;

@Component
public class CalculationImpl implements Calculation {
    @Override
    public int add(int x, int y) {
        return x+y;
    }

    @Override
    public int multiply(int x, int y) {
        return x*y;
    }
}

切面类

package com.test.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

//注解表示切面
@Aspect
@Component
public class LoggingAspect {
    //前置通知,匹配相应的方法
    @Before("execution(public int com.test.aop.CalculationImpl.*(int, int))")
    public void beforeMethod(JoinPoint joinpoint){
        String methodName=joinpoint.getSignature().getName();
        List<Object> params= Arrays.asList(joinpoint.getArgs());

        System.out.println("The method is "+methodName+" params are "+params);
    }
}

测试运行类Main

package com.test.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class Main {
    public static void main(String[] args){
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
        Calculation calculation=applicationContext.getBean(Calculation.class);
        int result=calculation.add(3,4);
        System.out.println("result="+result);
    }
}

spring配置文件:applicationContext.xml

<?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:context="http://www.springframework.org/schema/context"
       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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

   <context:component-scan base-package="com.test.aop"></context:component-scan>

    <!--使Aspectj起作用-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

运行结果:

The method is add params are [3, 4]
result=7

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值