Spring AOP实例二

11 篇文章 0 订阅
3 篇文章 0 订阅

尽管AOP是个好东西,但是在实例一中看来定义一个切面还是比较复杂的,需要实现专门的接口,然后进行复杂的配置。这样着实繁琐了点,好在Spring改进了这一不足,我们已经可以使用@AspectJ注解非常容易的配置定义切面。
弄一个简单的例子,着手使用@AspectJ,这里展示下pom.xml需要添加的依赖。

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjtools -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>1.8.9</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
        </dependency>

        <!-- spring 依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
package com.smart.aspectj.aspectj;

public class PersonImpl implements Person {
    public void eating() {
        System.out.println("我要吃饭了");
    }
    public void sleeping() {
        System.out.println("我要睡觉了");
    }
}

同样,我们需要在sleeping处织入增强。

@Aspect // 通过该注解将 PreSleepingAspect 标识为一个切面
public class PreSleepingAspect {
    @Before("execution(* sleeping(..))") // 定义切点和增强类型
    public void beforeSleeping() {// 增强的横切逻辑
        System.out.println("睡前要刷牙两分钟!");
    }
}

使用起来真的很简单,在这个横切逻辑处,我们没有继承任何接口,只是使用@Aspect注解。代码中的@Before注解则表示的这次增强类型,为前置增强,表示在目标方法执行前实施增强。execution(* sleeping(..))称之为切点表达式,execution为关键字,* sleeping(..)为操作参数。在这个实例中,execution代表目标类的某一执行方法,* sleeping(..)则是用于匹配该目标方法的字符串。
下面,我们实现为PersonImpl 生成织入PreSleepingAspect 切面的代理。

 Person target = new PersonImpl();
         AspectJProxyFactory factory = new AspectJProxyFactory();
         // 设置目标对象
         factory.setTarget(target);
         // 添加切面类
         factory.addAspect(PreSleepingAspect.class);
         // 生成织入切面的代理对象
         Person proxy = factory.getProxy();
         proxy.eating();
         proxy.sleeping();

运行结果如下:
这里写图片描述
效果杠杠的。
但是其实这样生成代理还是不够简洁,一般情况下,都是通过Spring的配置完成切面织入操作的。

<?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-4.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
    <aop:aspectj-autoproxy />
    <!--bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/ -->
    <bean id="person" class="com.smart.aspectj.aspectj.PersonImpl" />
    <bean class="com.smart.aspectj.aspectj.PreSleepingAspect" />
</beans>

通过 aop:aspectj-autoproxy 自动为Spring容器中那些匹配@AspectJ切面的Bean创建代理,完成切面织入。

    ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:bean.xml");
        Person target = (Person) context.getBean("person");
        target.eating();
        target.sleeping();

简单方便,效果一样杠杠的。
另外,如果想要在切面中获得连接点信息,添加参数类型JoinPoint

@Aspect // 通过该注解将 PreSleepingAspect 标识为一个切面
public class PreSleepingAspect {
    @Before("execution(* sleeping(..))") // 定义切点和增强类型
    public void beforeSleeping(JoinPoint jp) throws Throwable {// 增强的横切逻辑
        // 获得目标方法所属类的类名
        System.out.println(jp.getSignature().getDeclaringTypeName());
        // 获得目标方法名
        System.out.println(jp.getSignature().getName());
        // 获得目标参数
        System.out.println(jp.getArgs());
        System.out.println("睡前要刷牙两分钟!");
    }
}

JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象.
常用api:

方法名 功能
Signature getSignature(); 获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息
Object[] getArgs(); 获取传入目标方法的参数对象
Object getTarget(); 获取被代理的对象
Object getThis(); 获取代理对象
ProceedingJoinPoint对象

ProceedingJoinPoint对象是JoinPoint的子接口,该对象只用在@Around的切面方法中,
添加了
Object proceed() throws Throwable //执行目标方法
Object proceed(Object[] var1) throws Throwable //传入的新的参数去执行目标方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值