实现AOP

方法一:使用@Aspect注解

由于Spring只支持XML式而没有实现注解式(也叫AspectJ式)的AOP,所以,要使用@Aspect 注解,只能引入AspectJ相关依赖包 ,也就是:aspectjrt.jar 与 aspectjweaver.jar。

package chapter4;

import org.aspectj.lang.annotation.*;

@Aspect
public class Audience {
    @Pointcut("execution(* chapter4.Musician.perform(..))")  //如果Musician是某个接口(A)的实现,使用的时候应直接使用接口类型,即A a;a.perform();
    public void performance(){}

    @Before("performance()")
    public void silenceCellPhone()
    {
        System.out.println("手机静音");
    }
    @Before("performance()")
    public void takeSeats()
    {
        System.out.println("坐下");
    }

    @AfterReturning("performance()")
    public void applause()
    {
        System.out.println("鼓掌");
    }

    @AfterThrowing("performance()")
    public void fail()
    {
        System.out.println("失败");
    }
}
package chapter4;

import org.springframework.stereotype.Component;

@Component
public class Musician{
    public void perform() {
        System.out.println("音乐家表演了");
    }
}
package chapter4;

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;

import static org.junit.Assert.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = chapter4Config.class)
public class Chapter4Test {

    @Autowired
    Musician musician;

    @Test
    public void test()
    {
        musician.perform();
    }
}
运行结果
手机静音
坐下
音乐家表演了
鼓掌
创建环绕通知

将Audience代码改为以下,其他不变。

package chapter4;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
@Aspect
public class Audience {
    @Pointcut("execution(* chapter4.Musician.perform(..))")
    public void performance(){}
    @Around("performance()")
    public void watchPerformance(ProceedingJoinPoint jp) {
        try {
            System.out.println("手机静音");
            System.out.println("坐下");
            jp.proceed();
            System.out.println("鼓掌");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("失败");
        }
    }
}

        运行程序后可以看到,这个通知所达到的效果与之前的前置通知与后置通知是一样的。但是,现在他们位于同一个方法之中,不像之前那样分散在四个不同的通知方法里。

        

方法二:使用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: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">

        <!--启用Aspect自动代理-->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

        <bean id="musician" class="chapter4.Musician"></bean>
        <bean id="audience" class="chapter4.Audience"></bean>

        <aop:config>
                <aop:aspect ref="audience">
                        <aop:pointcut id="perform" expression="execution(* chapter4.Musician.perform(..))"/>
                        <aop:before pointcut-ref="perform" method="silenceCellPhone" />
                        <aop:before pointcut-ref="perform" method="takeSeats" />
                        <aop:after pointcut-ref="perform" method="applause"/>
                </aop:aspect>
        </aop:config>
</beans>
package chapter4;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

public class Audience {
    
    public void silenceCellPhone()
    {
        System.out.println("手机静音");
    }
    
    public void takeSeats()
    {
        System.out.println("坐下");
    }

    public void applause()
    {
        System.out.println("鼓掌");
    }

    @AfterThrowing("performance()")
    public void fail()
    {
        System.out.println("失败");
    }

}
package chapter4;

import org.springframework.context.annotation.*;

@Configuration
@ImportResource("classpath:chapter4.xml") //注入xml资源
@ComponentScan
public class chapter4Config {

    @Bean
    public Audience audience()
    {
        return new Audience();
    }
}

运行结果与前面一样。






AOP(Aspect Oriented Programming)是一种编程思想,它的核心是将横切关注点(Cross-Cutting Concerns)从主逻辑中分离出来,使得程序的各个部分之间更加松耦合、易于维护和扩展。在Java中,AOP通常通过使用AspectJ或Spring AOP框架来实现。 下面是一个简单的AOP示例,假设我们有一个计算器类Calculator,其中有一个add方法: ```java public class Calculator { public int add(int a, int b) { return a + b; } } ``` 现在我们想要在add方法执行前后记录日志,我们可以使用AOP实现: 1. 定义一个切面类,该类包含一个方法用于记录日志: ```java public class LoggingAspect { public void beforeAdd(JoinPoint joinPoint) { System.out.println("Before add method: " + joinPoint.getSignature().getName()); } public void afterAdd(JoinPoint joinPoint, Object result) { System.out.println("After add method: " + joinPoint.getSignature().getName() + ", result: " + result); } } ``` 2. 在Spring配置文件中定义切面: ```xml <bean id="calculator" class="com.example.Calculator"/> <bean id="loggingAspect" class="com.example.LoggingAspect"/> <aop:config> <aop:aspect ref="loggingAspect"> <aop:pointcut id="addOperation" expression="execution(* com.example.Calculator.add(int, int))"/> <aop:before pointcut-ref="addOperation" method="beforeAdd"/> <aop:after-returning pointcut-ref="addOperation" returning="result" method="afterAdd"/> </aop:aspect> </aop:config> ``` 3. 使用该计算器类: ```java public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Calculator calculator = context.getBean("calculator", Calculator.class); int result = calculator.add(1, 2); System.out.println("Result: " + result); } ``` 输出结果: ``` Before add method: add After add method: add, result: 3 Result: 3 ``` 在这个示例中,我们定义了一个切面类LoggingAspect,其中包含了两个方法,用于记录add方法执行前后的日志。我们在Spring配置文件中定义了一个切入点(pointcut),用于匹配Calculator类中的add方法。然后我们使用<aop:before>和<aop:after-returning>元素将切面类中的方法与切入点关联起来。最后,我们使用ApplicationContext来获取Calculator实例,并调用add方法,此时切面类中定义的方法会在add方法执行前后自动被调用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值