springAOP中的target、this、within的区别

前言

关于这三者的区别,在网上找到的资料不多,大多是AspectJ的资料,并且大量的copy,查阅官方文档后,自己又做了一些实验,最终有了这篇博客,因为是自己摸索的结果,并且没有阅读相应源码,如有错误,欢迎指出(有空还是把markdown给看了,csdn的排版不是很喜欢...........

 

target

target匹配目标对象的类型,即被代理对象的类型,例如A继承了B接口,则使用target("B"),target("A")均可以匹配到A

 

this

this匹配的是代理对象的类型,例如存在一个接口B,使用this("B"),如果某个类A的JDK代理对象类型为B,则A实现的接口B的方法会作为切点进行织入。

this的匹配结果和最终生成的代理对象互不干涉,对于this(M),当M为类时,若一个类的CGLIB代理类型为M,该类的所有方法作为连接点织入到CGLIB代理对象中,当M为接口时,若一个类的JDK代理类型为M,该类实现的接口方法作为连接点织入JDK代理对象中,this的匹配结果不会影响spring生成代理对象的方式,若一个类继承了接口,则使用JDK代理,否则使用CGLIB代理,这就会出现下列情况:

A继承了B接口,this("A")会匹配到A的CGLIB代理,接着将A的所有方法织入到A的CGLIB代理对象中,但是因为A继承了B接口,所以spring

生成的是JDK代理对象,并不会因为this("A")的存在而生成CGLIB代理,我们来看一个例子:

项目结构:

Roleinterface:

package com.springdemo3;

public interface Roleinterface {
     void print();
}

Roleimplement:

package com.springdemo3;

public class Roleimplement implements Roleinterface{
	
	public void print() {
		System.out.println("this is AOP");
	}
	
}

AOP切面

import org.aspectj.lang.annotation.After;
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 AOP {

	@Pointcut("this(com.springdemo3.Roleimplement)")
	public void print() {};
	
	@Before("print()")
	public void beforeprint() {
		System.out.println("这是前置方法");
	}
	
	@After("print()")
	public void afterprint() {
		System.out.println("这是后置方法");
	}
	
	@AfterReturning("print()")
	public void afterreturning() {
		System.out.println("正常返回");
	}
	
	@AfterThrowing("print()")
	public void afterthrowing() {
		System.out.println("异常防护");
	}
}

通过CGLIB匹配,会决定将Roleimplement的所有方法织入到CGLIB代理中,但是Roleimplement继承了接口,所以生成的是JDK代理,此时不会有方法被拦截

 

configurations类(配置类):

package com.springdemo3;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Bean;

@Configuration
@EnableAspectJAutoProxy
public class configurations {

	
	@Bean
	public Roleimplement getRoleinplement() {
		return new Roleimplement();
	}
	
	@Bean
	public AOP getAOP() {
		return new AOP();
	}
}

 

App类(运行类)

package com.springdemo3;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 *
 */
public class App 
{
    public static void main( String[] args )
    {
    	ApplicationContext ctx = new AnnotationConfigApplicationContext(configurations.class);
    	Roleinterface temp=(Roleinterface)ctx.getBean(Roleinterface.class);
    	temp.print();
    }
}

 

结果:

为了证明生成的是JDK代理,通过设置断点查看

如果我们强制spring使用CGLIB代理:

在springdemo3.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop 
    	http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
        >
<context:annotation-config/>
<aop:config proxy-target-class="true"/>
</beans>

xml中的某些命名空间是可以去掉,最重要的是加上<context:annotation-config/>

在@Configuration中使用注解:

@ImportResource("springdemo3.xml")

运行结果:

设置断点查看:

within

within比较严格,它是严格匹配被代理对象类型的,不会理会继承关系,例如A继承了接口B,则within("B")不会匹配到A,但是within("B+")可以匹配到A

 

 

Spring AOP 是一个用于实现面向切面编程的框架。它可以通过配置来实现横切关注点的模块化,并将其应用到程序的不同部分。Spring AOP 使用 AspectJ 切入点指示符来定义切入点表达式,用于匹配方法执行连接点。Spring AOP 支持以下 AspectJ 切入点指示符: 1. execution:用于匹配方法执行连接点。这是使用 Spring AOP 时要使用的主要切入点指示符。 2. within:限制匹配以连接某些类型的点(使用 Spring AOP 时在匹配类型声明的方法的执行)。 3. this:限制匹配到连接点(使用 Spring AOP 时方法的执行),其 Bean 引用(Spring AOP 代理)是给定类型的实例。 4. target:限制匹配到连接点(使用 Spring AOP 时方法的执行),其目标对象(正在代理的应用程序对象)是给定类型的实例。 5. args:限制匹配到连接点(使用 Spring AOP 时方法的执行),其参数是给定类型的实例。 6. @target:限制匹配到连接点(使用 Spring AOP 时方法的执行),其执行对象的类具有给定类型的注释。 7. @args:限制匹配到连接点(使用 Spring AOP 时方法的执行),其传递的实际参数的运行时类型具有给定类型的注释。 8. @within:限制匹配以连接具有给定注释的类型的点(使用 Spring AOP 时在具有给定注释的类型声明的方法的执行)。 9. @annotation:限制匹配到连接点的主题(在 Spring AOP 运行的方法)具有给定注释的连接点。 在使用 Spring AOP 时,需要引入 Spring AOPSpring Context 相关的包,并在配置文件进行相应的配置。可以通过 Maven 或其他构建工具来引入相关依赖。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值