Spring-AOP @AspectJ切点函数之within()

简介: Spring-AOP @AspectJ切点函数之within()

概述


通过类匹配模式串声明切点,within()函数定义的连接点是针对目标类而言的,而非针对运行期对象的类型而言,这一点和execution()是相同的。


但是within()和execution()函数不同的是,within()所指定的连接点最小范围只能是类,而execution()所指定的连接点可以大到包,小到方法入参。 所以从某种意义上讲,execution()函数功能涵盖了within()函数的功能


语法


within(<类匹配模式>)


比如 within(com.xgj.NaiveWaiter),是within()函数能表达的最小粒度。


用法举例:


within(com.xgj.NaiveWaiter) 匹配目标类NaiveWaiter的所有方法。 如果切点调整为within(com.xgj.Waiter),则NaiveWaiter和NaughtyWaiter中的所有方法都不匹配。 而Waiter本身是接口,不可能实例化,所以within(com.xgj.Waiter)的声明是无意义的。


within(com.xgj.*) 匹配com.xgj包中的所有类的方法,但是不包含子孙包中类的方法。


within(com.xgj..*)匹配com.xgj包以及子孙包中的所有类的方法都匹配这个切点


within(@com.xgj.Mark *) 匹配com.xgj及子包下带有@com.xgj.Mark 注解的任何类(接口不行)的任何方法


实例

代码已托管到Github—> https://github.com/yangshangwei/SpringMaster


within(com.xgj.NaiveWaiter)

20170905133006295.jpg


接口类

package com.xgj.aop.spring.advisor.aspectJ.function.within;
public interface Waiter {
    void greetTo(String clientName);
    void serverTo(String clientName);
}


注解标注的2个POJO

package com.xgj.aop.spring.advisor.aspectJ.function.within;
import org.springframework.stereotype.Component;
/**
 * 
 * 
 * @ClassName: NaughtyWaiter
 * 
 * @Description: @Component标注的bean
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 上午1:31:10
 */
@Component
public class NaughtyWaiter implements Waiter {
    @Override
    public void greetTo(String clientName) {
        System.out.println("NaughtyWaiter greetTo " + clientName);
    }
    @Override
    public void serverTo(String clientName) {
        System.out.println("NaughtyWaiter greetTo " + clientName);
    }
}
package com.xgj.aop.spring.advisor.aspectJ.function.within;
import org.springframework.stereotype.Component;
/**
 * 
 * 
 * @ClassName: NaiveWaiter
 * 
 * @Description: @Component标注的Bean
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 上午1:30:52
 */
@Component
public class NaiveWaiter implements Waiter {
    @Override
    public void greetTo(String clientName) {
        System.out.println("NaiveWaiter greetTo " + clientName);
    }
    @Override
    public void serverTo(String clientName) {
        System.out.println("NaiveWaiter serverTo " + clientName);
    }
}

增强切面

package com.xgj.aop.spring.advisor.aspectJ.function.within;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
/**
 * 
 * 
 * @ClassName: WithinAspect
 * 
 * @Description: 标注了@Aspect的切面
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 上午1:21:17
 */
@Aspect
public class WithinAspect {
    @AfterReturning("within(com.xgj.aop.spring.advisor.aspectJ.function.within.NaiveWaiter)")
    public void crossCuttingCode() {
        System.out.println("后置增强 some logic is here\n");
    }
}


配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    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
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">
<!-- (1)声明Context命名空间以及Schema文件   (2)扫描类包以及应用注解定义的bean -->
<context:component-scan base-package="com.xgj.aop.spring.advisor.aspectJ.function.within"/>
<!-- 基于@AspectJ切面的驱动器 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- 使用了@AspectJ注解的切面类 -->
<bean class="com.xgj.aop.spring.advisor.aspectJ.function.within.WithinAspect"/>
</beans>


测试类

package com.xgj.aop.spring.advisor.aspectJ.function.within;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class WithinAspectTest {
    @Test
    public void test() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "com/xgj/aop/spring/advisor/aspectJ/function/within/conf-within.xml");
        NaiveWaiter naiveWaiter = ctx.getBean("naiveWaiter", NaiveWaiter.class);
        naiveWaiter.greetTo("XiaoGongJiang");
        naiveWaiter.serverTo("XiaoGongJiang");
        NaughtyWaiter naughtyWaiter = ctx.getBean("naughtyWaiter",
                NaughtyWaiter.class);
        naughtyWaiter.greetTo("XiaoGongJiang");
        naughtyWaiter.serverTo("XiaoGongJiang");
    }
}


运行结果:

2017-09-05 01:32:21,687  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@24b9371e: startup date [Tue Sep 05 01:32:21 BOT 2017]; root of context hierarchy
2017-09-05 01:32:21,786  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/function/within/conf-within.xml]
NaiveWaiter greetTo XiaoGongJiang
后置增强 some logic is here
NaiveWaiter serverTo XiaoGongJiang
后置增强 some logic is here
NaughtyWaiter greetTo XiaoGongJiang
NaughtyWaiter greetTo XiaoGongJiang


可以看到,只有NaiveWaiter类被织入了横切逻辑。

如果我们将切面中的within函数改为within(com.xgj.aop.spring.advisor.aspectJ.function.within.Waiter)

@Aspect
public class WithinAspect {
    @AfterReturning("within(com.xgj.aop.spring.advisor.aspectJ.function.within.Waiter)")
    public void crossCuttingCode() {
        System.out.println("后置增强 some logic is here\n");
    }
}

再此运行

2017-09-05 01:33:27,989  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@61ee30d2: startup date [Tue Sep 05 01:33:27 BOT 2017]; root of context hierarchy
2017-09-05 01:33:28,066  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/function/within/conf-within.xml]
NaiveWaiter greetTo XiaoGongJiang
NaiveWaiter serverTo XiaoGongJiang
NaughtyWaiter greetTo XiaoGongJiang
NaughtyWaiter greetTo XiaoGongJiang


within(com.xgj.*)

先增加一个子目录seller, 然后 改造下 切面类


20170905134124584.jpg


@Aspect
public class WithinAspect {
    // 匹配com.xgj.aop.spring.advisor.aspectJ.function.within包下的所有类的所有方法,不包括子孙包
    @AfterReturning("within(com.xgj.aop.spring.advisor.aspectJ.function.within.*)")
    public void crossCuttingCode() {
        System.out.println("后置增强 some logic is here\n");
    }
}

测试类获取SmartSeller,然后调用目标方法

package com.xgj.aop.spring.advisor.aspectJ.function.within;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.xgj.aop.spring.advisor.aspectJ.function.within.seller.SmartSeller;
public class WithinAspectTest {
    @Test
    public void test() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "com/xgj/aop/spring/advisor/aspectJ/function/within/conf-within.xml");
        NaiveWaiter naiveWaiter = ctx.getBean("naiveWaiter", NaiveWaiter.class);
        naiveWaiter.greetTo("XiaoGongJiang");
        naiveWaiter.serverTo("XiaoGongJiang");
        NaughtyWaiter naughtyWaiter = ctx.getBean("naughtyWaiter",
                NaughtyWaiter.class);
        naughtyWaiter.greetTo("XiaoGongJiang");
        naughtyWaiter.serverTo("XiaoGongJiang");
        SmartSeller smartSeller = ctx.getBean("smartSeller", SmartSeller.class);
        smartSeller.smileTo("XiaoGongJiang");
        smartSeller.jokeTo("XiaoGongJiang");
    }
}


运行结果:

2017-09-05 01:39:44,352  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@a06514b: startup date [Tue Sep 05 01:39:44 BOT 2017]; root of context hierarchy
2017-09-05 01:39:44,433  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/function/within/conf-within.xml]
NaiveWaiter greetTo XiaoGongJiang
后置增强 some logic is here
NaiveWaiter serverTo XiaoGongJiang
后置增强 some logic is here
NaughtyWaiter greetTo XiaoGongJiang
后置增强 some logic is here
NaughtyWaiter greetTo XiaoGongJiang
后置增强 some logic is here
SmartSeller serverTo XiaoGongJiang
SmartSeller greetTo XiaoGongJiang


可以看到,只有当前目录下的所有类的方法被织入了横切逻辑,而子孙包中的没有被织入增强。


within(com.xgj..*)

改造下切面类

@Aspect
public class WithinAspect {
    // 匹配com.xgj.aop.spring.advisor.aspectJ.function.within包下的所有类的所有方法,包括子孙包
    @AfterReturning("within(com.xgj.aop.spring.advisor.aspectJ.function.within..*)")
    public void crossCuttingCode() {
        System.out.println("后置增强 some logic is here\n");
    }
}


再此运行

2017-09-05 01:42:56,488  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@a06514b: startup date [Tue Sep 05 01:42:56 BOT 2017]; root of context hierarchy
2017-09-05 01:42:56,599  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/function/within/conf-within.xml]
NaiveWaiter greetTo XiaoGongJiang
后置增强 some logic is here
NaiveWaiter serverTo XiaoGongJiang
后置增强 some logic is here
NaughtyWaiter greetTo XiaoGongJiang
后置增强 some logic is here
NaughtyWaiter greetTo XiaoGongJiang
后置增强 some logic is here
SmartSeller serverTo XiaoGongJiang
后置增强 some logic is here
SmartSeller greetTo XiaoGongJiang
后置增强 some logic is here

可以看到,子孙包中的所有类的所有方法都能被织入了增强.


within(@com.xgj.Mark *)

增加一个自定义的注解,或者使用框架自带的注解 都可以,用于测试

package com.xgj.aop.spring.advisor.aspectJ.function.within;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 
 * 
 * @ClassName: Mart
 * 
 * @Description: 自定义注解
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 下午12:02:46
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface Mart {
    public String value() default "";
}

NaiveWaiter类标注@Mart

package com.xgj.aop.spring.advisor.aspectJ.function.within;
import org.springframework.stereotype.Component;
/**
 * 
 * 
 * @ClassName: NaiveWaiter
 * 
 * @Description: @Component标注的Bean
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 上午1:30:52
 */
@Mart
@Component
public class NaiveWaiter implements Waiter {
    @Override
    public void greetTo(String clientName) {
        System.out.println("NaiveWaiter greetTo " + clientName);
    }
    @Override
    public void serverTo(String clientName) {
        System.out.println("NaiveWaiter serverTo " + clientName);
    }
}


NaughtyWaiter没有类标注@Mart

子目录 SmartSeller 标注 @Mart

package com.xgj.aop.spring.advisor.aspectJ.function.within.seller;
import org.springframework.stereotype.Component;
import com.xgj.aop.spring.advisor.aspectJ.function.within.Mart;
/**
 * 
 * 
 * @ClassName: SmartSeller
 * 
 * @Description: @Component标注的Bean
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 上午1:30:52
 */
@Mart
@Component
public class SmartSeller {
    public void jokeTo(String clientName) {
        System.out.println("SmartSeller greetTo " + clientName);
    }
    public void smileTo(String clientName) {
        System.out.println("SmartSeller serverTo " + clientName);
    }
}

修改切面

@AfterReturning("within(@com.xgj.aop.spring.advisor.aspectJ.function.within.Mart *)")
    public void crossCuttingCode() {
        System.out.println("后置增强 some logic is here\n");
    }


运行测试类

2017-09-05 17:50:54,071  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@54397c28: startup date [Tue Sep 05 17:50:54 BOT 2017]; root of context hierarchy
2017-09-05 17:50:54,179  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/function/within/conf-within.xml]
NaiveWaiter greetTo XiaoGongJiang
后置增强 some logic is here
NaiveWaiter serverTo XiaoGongJiang
后置增强 some logic is here
NaughtyWaiter greetTo XiaoGongJiang
NaughtyWaiter greetTo XiaoGongJiang
SmartSeller serverTo XiaoGongJiang
后置增强 some logic is here
SmartSeller greetTo XiaoGongJiang
后置增强 some logic is here


匹配com.xgj.aop.spring.advisor.aspectJ.function.within及子包下带有@com.xgj.aop.spring.advisor.aspectJ.function.within.Mark 注解的任何类(接口不行)的任何方法

相关文章
|
5月前
|
XML Java API
Spring AOP切点和通知机制的深度解析
Spring AOP切点和通知机制的深度解析
84 4
|
5月前
|
Java Serverless 应用服务中间件
Serverless 应用引擎产品使用合集之Web函数启动的Spring Boot项目可以通过什么方式配置Nginx
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
5月前
|
XML 缓存 Java
浅浅了解下Spring中生命周期函数(Spring6全攻略)
Spring框架设计生命周期回调函数的主要目的是为了提供一种机制,使开发人员能够在对象创建、初始化和销毁等生命周期阶段执行特定的操作。这种机制可以帮助开发人员编写更加灵活和可维护的代码。
34 0
|
6月前
|
Java 开发者 Spring
Spring AOP的切点是通过使用AspectJ的切点表达式语言来定义的。
【5月更文挑战第1天】Spring AOP的切点是通过使用AspectJ的切点表达式语言来定义的。
71 5
|
6月前
|
监控 Java 测试技术
Spring Boot与事务钩子函数:概念与实战
【4月更文挑战第29天】在复杂的业务逻辑中,事务管理是确保数据一致性和完整性的关键。Spring Boot提供了强大的事务管理机制,其中事务钩子函数(Transaction Hooks)允许开发者在事务的不同阶段插入自定义逻辑。本篇博客将详细探讨事务钩子函数的概念及其在Spring Boot中的应用。
176 1
|
6月前
Spring5源码(31)-基于@AspectJ的AOP
Spring5源码(31)-基于@AspectJ的AOP
49 0
|
6月前
|
XML Java 数据格式
Spring-AOP @AspectJ语法基础
Spring-AOP @AspectJ语法基础
79 0
|
消息中间件 Java Kafka
Spring 事务的独门绝技:钩子函数的使用技巧
经过前面对Spring AOP、事务的总结,我们已经对它们有了一个比较感性的认知了。今天,我继续安利一个独门绝技:Spring 事务的钩子函数。单纯的讲技术可能比较枯燥乏味。接下来,我将以一个实际的案例来描述Spring事务钩子函数的正确使用姿势。
Spring 事务的独门绝技:钩子函数的使用技巧
|
Java Spring
AOP之切点
AOP之切点
|
2月前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
AOP(面向切面编程)能够帮助我们在不修改现有代码的前提下,为应用程序添加新的功能或行为。Micronaut框架中的AOP模块通过动态代理机制实现了这一目标。AOP将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高模块化程度。在Micronaut中,带有特定注解的类会在启动时生成代理对象,在运行时拦截方法调用并执行额外逻辑。例如,可以通过创建切面类并在目标类上添加注解来记录方法调用信息,从而在不侵入原有代码的情况下增强应用功能,提高代码的可维护性和可扩展性。
64 1