spring AspectJ书店打折促销案例

一间书店开始打折促销,规则是每一名顾客只能买一本书,而且已经脱销了,要求顾客进门,显示欢迎信息,当顾客买完书,显示欢送信息,没书时,请仓库赶快订货;使用基于XML的AspectJ完成

首先,我们需要定义一个切入点,来标识我们要拦截的方法,也就是顾客购买书的方法:


<aspectj:pointcut id="bookPurchase" expression="execution(* com.example.BookStore.purchaseBook(..))"/>

然后,我们需要定义一个切面,来实现我们的切面逻辑:


<aspectj:aspect id="discountAspect" ref="discountBean">
    <aspectj:before pointcut-ref="bookPurchase" method="greetCustomer"/>
    <aspectj:after-returning pointcut-ref="bookPurchase" method="thankCustomer"/>
    <aspectj:after-throwing pointcut-ref="bookPurchase" throwing="ex" method="orderStock"/>
</aspectj:aspect>

这里定义了三个通知:

before通知,在执行切入点方法前执行,用于向顾客发送欢迎信息。
after-returning通知,在执行切入点方法后执行,用于向顾客发送欢送信息。
after-throwing通知,在切入点方法抛出异常时执行,用于向仓库发送订货信息。
在切面中,我们需要引用一个实现了具体逻辑的Bean,这里称为discountBean,并在aspect标签的ref属性中指定该Bean的ID。

下面是具体的实现代码:


public class Discount {
 
    public void greetCustomer() {
        System.out.println("Welcome to our book store!");
    }
 
    public void thankCustomer() {
        System.out.println("Thank you for shopping with us!");
    }
 
    public void orderStock(Throwable ex) {
        System.out.println("Sorry, the book is out of stock. Please order more.");
    }
}

最后,我们需要在Spring配置文件中将切面和切入点关联起来:

<aop:config>
    <aop:aspect id="discountAspect" ref="discountBean">
        <aop:before pointcut-ref="bookPurchase" method="greetCustomer"/>
        <aop:after-returning pointcut-ref="bookPurchase" method="thankCustomer"/>
        <aop:after-throwing pointcut-ref="bookPurchase" throwing="ex" method="orderStock"/>
    </aop:aspect>
</aop:config>

下面是一个基于XML的完整Spring配置文件示例,包含了定义Bean、依赖注入、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"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

    <!-- 定义Bean -->
    <bean id="bookDao" class="com.example.dao.BookDaoImpl">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
    <bean id="bookService" class="com.example.service.BookServiceImpl">
        <property name="bookDao" ref="bookDao"/>
    </bean>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
        <property name="username" value="root"/>
        <property name="password" value="password"/>
    </bean>

    <!-- 依赖注入 -->
    <bean id="bookController" class="com.example.controller.BookController">
        <property name="bookService" ref="bookService"/>
    </bean>

    <!-- AOP配置 -->
    <aop:aspectj-autoproxy/>
    <bean id="myAspect" class="com.example.aspect.MyAspect"/>
    
    <!-- 事务管理配置 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
</beans>

其中,通过元素定义了三个Bean:bookDao、bookService和dataSource,并分别设置了它们的属性和依赖关系。通过元素实现依赖注入。在bookController中注入了bookService,从而实现了Controller和Service的解耦。通过aop:aspectj-autoproxy元素启用AspectJ切面自动代理功能,并通过元素定义切面类myAspect。通过tx:annotation-driven元素启用注解式事务管理。