AOP-Aspect Oriented Programming

本文介绍了Spring框架中AOP(面向切面编程)的基本概念,包括Aspect、JoinPoint、Advice和PointCut等核心术语。并通过示例展示了如何使用Spring配置文件定义切点和通知,实现方法级别的拦截。

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

简介

Spring中AOP的实现就是通过动态代理来实现的。

重要概念

Aspect(切面):对象操作过程中的截面。如权限检查、日志、事务处理等。
Join Point(连接点):程序运行中的某个阶段点。如某个方法调用,异常抛出等。
Advice(处理逻辑):某个连接点所采用的处理逻辑。
PointCut(切点):一系列连接点的集合,它指明Advice在什么时候被触发。

实现

JDK实现

spring实现

<bean id="myPointcutAdvisor" 
    class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> 
    <property name="advice"> 
        <ref local="MyInterceptor" /> 
    </property> 
    <property name="patterns"> 
        <list> 
            <value>.*save.*</value> 
            <value>.*do.*</value> 
        </list> 
    </property> 
</bean>

上面我们针对MyInterceptor设定了一个基于方法名的触发条件,也就是说,当目标类的指定方法运行时,MyInterceptor即被触发。

最后,我们还需要定义一个Spring AOP ProxyFactory, 加载执行AOP组件,并且需要将Advice通过IOC的方式注入到接口以及实现类。


  对应的配置文件应如下配置从而实现这些内容: 
<bean id="myAOPProxy"   class="org.springframework.aop.framework.ProxyFactoryBean"> 
    <property name="proxyInterfaces"> 
        <value>test.aop.spring.DomainObjDAO</value> 
    </property> 
    <property name="target"> 
        <ref local="impl" /> 
    </property> 
    <property name="interceptorNames"> 
        <value>myPointcutAdvisor</value> 
    </property> 
</bean> 

测试

ApplicationContext ctx=new FileSystemXmlApplicationContext("test/Bean.xml"); 
test = (DomainObjDAO) ctx.getBean("myAOPProxy"); 

ProxyFactoryBean 源码

import java.net.SocketAddress;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

/**
 * {@link FactoryBean} that creates a {@link Proxy java.net.Proxy}.
 *
 * @author Arjen Poutsma
 * @since 3.0.4
 * @see FactoryBean
 * @see Proxy
 */
public class ProxyFactoryBean implements FactoryBean<Proxy>, InitializingBean {

    private Proxy.Type type = Proxy.Type.HTTP;

    private String hostname;

    private int port = -1;

    private Proxy proxy;

    /**
     * 设置代理类型. 默认设置成 {@link java.net.Proxy.Type#HTTP}.
     */
    public void setType(Proxy.Type type) {
        this.type = type;
    }

    /**
     * 设置代理主机名称
     */
    public void setHostname(String hostname) {
        this.hostname = hostname;
    }

    /**
     * 设置代理接口
     */
    public void setPort(int port) {
        this.port = port;
    }

    //重写InitializingBean 
    @Override
    public void afterPropertiesSet() throws IllegalArgumentException {
        Assert.notNull(type, "'type' must not be null");
        Assert.hasLength(hostname, "'hostname' must not be empty");
        Assert.isTrue(port >= 0 && port <= 65535, "'port' out of range: " + port);

        SocketAddress socketAddress = new InetSocketAddress(hostname, port);
        this.proxy = new Proxy(type, socketAddress);

    }

    //重写factoryBean
    @Override
    public Proxy getObject() {
        return proxy;
    }

    @Override
    public Class<?> getObjectType() {
        return Proxy.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
### 依赖注入(DI)、控制反转(IoC)与面向切面编程(AOP)的概念及关系 #### 一、概念定义 1. **控制反转(IoC, Inversion of Control)** 控制反转是一种设计原则,其核心思想是将对象的创建和管理权交给框架或容器,而非由程序本身手动处理。这种模式使得应用程序更加灵活且易于维护[^3]。 2. **依赖注入(DI, Dependency Injection)** 依赖注入是实现控制反转的一种具体方式。通过依赖注入,外部容器会自动为类提供所需的依赖项,从而减少耦合度并提高可测试性和扩展性。 3. **面向切面编程(AOP, Aspect-Oriented Programming)** 面向切面编程旨在分离业务逻辑中的横切关注点(如日志记录、安全性、事务管理等),使其独立于主要业务流程之外。在 Spring 中,AOP 利用动态代理技术,在不修改原有代码的情况下增强功能[^2]。 --- #### 二、原理分析 1. **控制反转(IoC)的工作原理** IoC 的工作原理主要是通过配置文件或者注解的方式告诉容器如何创建对象及其依赖关系。当需要某个对象时,容器会按照预设规则实例化该对象,并将其传递给调用方。 2. **依赖注入(DI)的具体实现** - 构造函数注入:通过构造函数参数传入依赖的对象。 - Setter 方法注入:通过设置属性的方法注入依赖。 - 接口注入:较少使用,通常指通过接口方法完成依赖注入。 下面是一个简单的依赖注入示例: ```java public class UserService { private UserRepository userRepository; @Autowired // 使用 Spring 注解实现 DI public UserService(UserRepository userRepository) { this.userRepository = userRepository; } public void getUser() { System.out.println(userRepository.findUser()); } } ``` 3. **面向切面编程(AOP)的核心机制** AOP 主要依靠拦截器模式,在指定的目标方法执行前/后插入额外的功能逻辑(称为通知 Advice)。这些通知可以分为前置通知 (@Before)、后置通知 (@AfterReturning)、异常通知 (@AfterThrowing) 和环绕通知 (@Around)。 --- #### 三、区别与联系 | 特性 | 控制反转 (IoC) | 依赖注入 (DI) | 面向切面编程 (AOP) | |--------------|----------------------------------------|-------------------------------------|------------------------------------| | **作用范围** | 管理对象生命周期 | 解决对象间的依赖 | 处理横切关注点 | | **实现方式** | 容器接管对象创建 | 容器负责注入依赖 | 动态代理技术应用于特定连接点 | | **相互关系** | IoC 是基础架构 | DI 是 IoC 的一种实现形式 | AOP 建立在 IoC 上 | - **IoC 与 DI 的关系**: IoC 是一种广义的设计理念,而 DI 是其实现手段之一。两者共同协作以降低组件间耦合程度。 - **IoC 与 AOP 的关系**: AOP 可视为 IoC 的延伸部分,因为它的正常运作离不开 IoC 容器的支持。例如,Spring AOP 所需的代理对象正是借助 IoC 来生成的[^1]。 - **DI 与 AOP 的关联**: 尽管二者侧重点不同——前者侧重于构建松散耦合系统;后者聚焦于隔离跨领域问题——但在实际开发过程中往往紧密结合在一起使用。 --- ### 示例代码展示 以下是结合 IoC、DI 和 AOP 的综合案例: ```java // 日志切面类 @Component @Aspect public class LoggingAspect { @Before("execution(* com.example.service.*.*(..))") // 定义切入点表达式 public void logBefore(JoinPoint joinPoint) { System.out.println("Method called: " + joinPoint.getSignature().getName()); } } // Service 类 @Service public class MyService { private final SomeDependency someDependency; @Autowired // 实现 DI public MyService(SomeDependency someDependency) { this.someDependency = someDependency; } public void performAction() { System.out.println("Performing action..."); } } ``` 上述代码片段展示了如何利用 Spring 框架同时实践 IoC、DI 和 AOP 技术。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值