Spring-AOP @AspectJ切点函数之target()和this()

简介: Spring-AOP @AspectJ切点函数之target()和this()

概述


target()切点函数通过判断目标类是否按类型匹配指定类来决定连接点是否匹配. 用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;


this()切点函数则通过判断代理类是否按类型匹配指定类来决定是否和切点匹配。 用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配。 this中使用的表达式必须是类型全限定名,不支持通配符。


两者都仅接受类名的入参,虽然类名可以带“+”,但是对于这两个函数来讲,使用或者不是用,效果完全相同。


实例

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


target()

target(M)表示如果目标类按类型匹配于M,这目标类的所有方法都匹配切点。


  • target(com.xgj.IBussiness) :IBussiness为接口,匹配接口实现类中所有方法,包括未在接口中声明的方法
  • target(com.xgj.IBussiness)等同于target(com.xgj.IBussiness+)


aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTcwOTA2MDgzODQ2Njc2.png


接口

package com.xgj.aop.spring.advisor.aspectJ.function.target;
public interface IBussinessService {
  String doSomething();
}


目标Bean

package com.xgj.aop.spring.advisor.aspectJ.function.target;
import org.springframework.stereotype.Component;
/**
 * 
 * 
 * @ClassName: BussinessService
 * 
 * @Description: @Component标注的bean
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 下午8:18:03
 */
@Component
public class BussinessService {
  public String doSomething() {
    System.out.println("doSomething executed");
    return "success";
  }
}


切面

package com.xgj.aop.spring.advisor.aspectJ.function.target;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
/**
 * 
 * 
 * @ClassName: TargetAspect
 * 
 * @Description: @Aspect标注的切面
 *               target(com.xgj.aop.spring.advisor.aspectJ.function.
 *               target.Class1)等同于
 *               target(com.xgj.aop.spring.advisor.aspectJ.function
 *               .target.Class1+)
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 下午7:53:52
 */
@Aspect
public class TargetAspect {
        @AfterReturning("target(com.xgj.aop.spring.advisor.aspectJ.function.target.IBussinessService)")
  public void crossCuttingCode() {
    System.out.println("some logic is here");
  }
}


配置文件

<?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.target"/>
<!-- 基于@AspectJ切面的驱动器 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- 使用了@AspectJ注解的切面类 -->
<bean class="com.xgj.aop.spring.advisor.aspectJ.function.target.TargetAspect"/>
</beans>


测试类

package com.xgj.aop.spring.advisor.aspectJ.function.target;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TargetAspectTest {
  private ApplicationContext applicationContext;
  @Test
  public void test() {
    applicationContext = new ClassPathXmlApplicationContext(
        "classpath:com/xgj/aop/spring/advisor/aspectJ/function/target/conf-target.xml");
    BussinessService bussinessService = applicationContext.getBean(
        "bussinessService", BussinessService.class);
    // 织入增强
    bussinessService.doSomething();
    // 织入增强
    bussinessService.doAnother();
  }
}


运行结果:

2017-09-05 20:37:52,147  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@285211ef: startup date [Tue Sep 05 20:37:52 BOT 2017]; root of context hierarchy
2017-09-05 20:37:52,264  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/function/target/conf-target.xml]
doSomething executed
some logic is here
doAnother executed
some logic is here


this()

一般情况下,使用this()和target()来匹配定义切点,二者是等效的

  • target(com.xgj.IBussiness)等价于 this(com.xgj.IBussiness)
  • target(com.xgj.BussinessService)等价于this(com.xgj.BussinessService)

二者的区别体现在通过引介切面产生代理对象时的具体表现。

看个例子:

aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTcwOTA2MTAwMTIwMjk3.png


接口

package com.xgj.aop.spring.advisor.aspectJ.function.thisFun;
public interface IBussinessService {
  String doBussiness();
}


实现类

package com.xgj.aop.spring.advisor.aspectJ.function.thisFun;
import org.springframework.stereotype.Component;
/**
 * 
 * 
 * @ClassName: BussinessService
 * 
 * @Description: @Component标注的bean
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 下午8:18:03
 */
@Component
public class BussinessService implements IBussinessService {
  @Override
  public String doBussiness() {
    System.out.println("doBussiness executed");
    return "success";
  }
  public String doAnother() {
    System.out.println("doAnother executed");
    return "success";
  }
}


另外一个通过引介切面要实现的接口

package com.xgj.aop.spring.advisor.aspectJ.function.thisFun;
public interface ITransportService {
  public void doTransport();
}


实现类

package com.xgj.aop.spring.advisor.aspectJ.function.thisFun;
public class TransportService implements ITransportService {
  @Override
  public void doTransport() {
    System.out.println("doTransport executed");
  }
}


为Bussiness添加 ITransportService接口的切面

package com.xgj.aop.spring.advisor.aspectJ.function.thisFun;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.core.Ordered;
/**
 * 
 * 
 * @ClassName: AddTransportForBussinessAspect
 * 
 * @Description: 为Bussiness添加 ITransportService接口的切面
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 下午9:18:50
 */
@Aspect
public class AddTransportForBussinessAspect implements Ordered {
  // (1)value 为BussinessService添加接口实现, (2)defaultImpl要添加的接口的默认的接口实现类
  @DeclareParents(value = "com.xgj.aop.spring.advisor.aspectJ.function.thisFun.BussinessService", defaultImpl = TransportService.class)
  public ITransportService iTransportService; // (3) 要实现的目标接口
  @Override
  public int getOrder() {
    return 2;
  }
}

横切逻辑切面

package com.xgj.aop.spring.advisor.aspectJ.function.thisFun;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.Ordered;
/**
 * 
 * 
 * @ClassName: ThisAspect
 * 
 * @Description: @Aspectn标注的切面
 * 
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 下午8:50:26
 */
@Aspect
public class ThisAspect implements Ordered {
  // 织入任何运行期对象为ITransportService的Bean中
  @AfterReturning("this(com.xgj.aop.spring.advisor.aspectJ.function.thisFun.ITransportService)")
  public void corssCuttingCode() {
    System.out.println("some logic is here \n ");
  }
  @Override
  public int getOrder() {
    return 1;
  }
}


配置文件

<?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.thisFun"/>
<!-- 基于@AspectJ切面的驱动器 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- 使用了@AspectJ注解的切面类 -->
<bean class="com.xgj.aop.spring.advisor.aspectJ.function.thisFun.ThisAspect"/>
<bean class="com.xgj.aop.spring.advisor.aspectJ.function.thisFun.AddTransportForBussinessAspect"/>
</beans>


测试类

package com.xgj.aop.spring.advisor.aspectJ.function.thisFun;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ThisAspectTest {
  private ApplicationContext applicationContext;
  @Test
  public void test() {
    applicationContext = new ClassPathXmlApplicationContext(
        "classpath:com/xgj/aop/spring/advisor/aspectJ/function/thisFun/conf-this.xml");
    BussinessService bussinessService = (BussinessService) applicationContext
        .getBean("bussinessService");
    // 匹配 this
    bussinessService.doBussiness();
    // 匹配 this
    bussinessService.doAnother();
    // 匹配 this
    ((ITransportService) bussinessService).doTransport();
  }
}


运行结果

2017-09-05 22:24:03,301  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@24177697: startup date [Tue Sep 05 22:24:03 BOT 2017]; root of context hierarchy
2017-09-05 22:24:03,397  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/function/thisFun/conf-this.xml]
doBussiness executed
some logic is here 
doAnother executed
some logic is here 
doTransport executed
some logic is here 


如果有多个切面,注意多切面织入的顺序,如果不加织入的顺序, doTransport 方法的切面无法织入。

可见代理对象的方法都织入了this()函数定义的切面。

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