Spring In Action 面向切面编程(AOP)

本文通过一个具体的例子介绍了面向切面编程(AOP)的概念及其在Spring框架中的应用方式。文章详细解释了AOP的基本术语,如通知(Advice)、连接点(Joinpoint)、切点(Pointcut)、切面(Aspect)和织入(Weaving),并通过实现一个表演者(Performer)接口的具体类和观众(Audience)切面来演示如何在Spring中配置和使用AOP。

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

   首先介绍AOP的术语,为了理解AOP,我们必须了解这些术语。

   Advice(通知):在AOP的术语中,切面的工作被称为通知

         Spring 中可以使用 5中类型的通知

                Before-在方法调用之前调用通知。

                After-在方法调用之后调用通知,无论方法执行是否成功。

                After-returning-在方法成功执行之后调用通知

                After-throwing-在方法抛出异常后调用通知

                Around-通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为

   Joinpoint(连接点):连接点是在应用执行过程中能够插入切面的一个点

   Pointcut(切点):如果说通知定义了切面的“什么”和“何时”,那么切丁就是定义了切面的“何处”。切点的定义会匹配通知所要织入的一个或多个连接点。

   切面(Aspect):切面是切点和通知的结合。通知和切点定义了关于切面的全部内容-它是在什么,在什么时候以及何处完成其功能。

  织入(Weaving):织入是将切面应用到目标对象来创建代理对象的过程。切面在指定的连接点被织入到切面对象中。在目标对象的生命周期中有多个点可以进行织入。

  •   编译期-切面在目标对象编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式织入切面的。
  • 类加载期-切面在目标对象加载到JVM时被织入。这种方式需要特殊的类加载器,它可以在目标对象被引入到应用中之前增强该类的字节码。
  • 运行期-切面在运行的某个时刻被织入。在一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代理对象。Spring AOP就是以这种方式织入切面的。

有如下接口

package spring.aop.perform;

public interface Performer {
void perform();
}
 
package spring.aop.perform;

import org.apache.log4j.Logger;

public class Juggler implements Performer {
private static Logger logger=Logger.getLogger(Juggler.class);
private int beanBags;

public void perform() {
logger.info("JUGGLING "+beanBags+"BEANBAGS");

}

public int getBeanBags() {
return beanBags;
}

public void setBeanBags(int beanBags) {
this.beanBags = beanBags;
}


}
 
切面
写道
package spring.aop.perform;

import org.apache.log4j.Logger;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class Audience {
private static Logger logger = Logger.getLogger(Audience.class);

@Pointcut("execution(* spring.aop.perform.Performer.perform(..))")
public void performance() {

}

@Before("performance()")
public void takeSeats() {
logger.info(" The audience is taking their seats.");
}

@Before("performance()")
public void turnOffCellPhone() {
logger.info("The audience is turning off the cellPhone");
}

@AfterReturning("performance()")
public void applaud() {
logger.info("CLAP CLAP....");
}

@AfterThrowing("performance()")
public void demandRefund() {
logger.info("Boo! We want my money back!");
}
}

 

 测试方法

写道
package spring.aop.perform;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:beans.xml")
public class PerformerTest {
@Autowired
private Performer juggler;

@Test
public void testPerform() {
juggler.perform();
}

}

 

写道
<context:component-scan base-package="spring.*">
 </context:component-scan>
 <aop:aspectj-autoproxy />
 <aop:config>
  <aop:aspect ref="audience">
   <aop:before pointcut="execution(* spring.aop.perform.Performer.perform(..))"
    method="takeSeats" />
   <aop:before pointcut="execution(* *.perform(..))"
    method="turnOffCellPhone" />
  </aop:aspect>
 </aop:config>
 <bean id="audience" class="spring.aop.perform.Audience" />

 [JMS] 609  - INFO  -2014-01-30 10:55:44,826 [main] org.springframework.context.support.GenericApplicationContext  - Bean 'scheduler' of type [class org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[JMS] 625  - INFO  -2014-01-30 10:55:44,842 [main] org.springframework.beans.factory.support.DefaultListableBeanFactory  - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@209444d1: defining beans [calculatorLogginAspect,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.aop.aspectj.AspectJPointcutAdvisor#0,org.springframework.aop.aspectj.AspectJPointcutAdvisor#1,audience,arithmeticCalculator,unitCalculator,executor,scheduler,org.springframework.context.annotation.internalAsyncAnnotationProcessor,org.springframework.context.annotation.internalScheduledAnnotationProcessor,juggler,connectionFactory,mailDestination,jmsTemplate,frontDesk,mailMessageConverter,backOffice,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
[JMS] 1094 - INFO  -2014-01-30 10:55:45,311 [main] spring.aop.perform.Audience  -  The audience is taking their seats.
[JMS] 1094 - INFO  -2014-01-30 10:55:45,311 [main] spring.aop.perform.Audience  -  The audience is taking their seats.
[JMS] 1094 - INFO  -2014-01-30 10:55:45,311 [main] spring.aop.perform.Audience  - The audience is turning off the cellPhone
[JMS] 1094 - INFO  -2014-01-30 10:55:45,311 [main] spring.aop.perform.Audience  - The audience is turning off the cellPhone
[JMS] 1094 - INFO  -2014-01-30 10:55:45,311 [main] spring.aop.perform.Juggler  - JUGGLING 3BEANBAGS
[JMS] 1094 - INFO  -2014-01-30 10:55:45,311 [main] spring.aop.perform.Audience  - CLAP CLAP....
[JMS] 1110 - INFO  -2014-01-30 10:55:45,327 [Thread-1] org.springframework.context.support.GenericApplicationContext  - Closing org.springframework.context.support.GenericApplicationContext@1a84da23: startup date [Thu Jan 30 10:55:44 CST 2014]; root of context hierarchy
[JMS]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈脩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值