AspectJ 使用 org.aspectj.lang.JoinPoint 接口表示目标类连接点对象,如果是环绕增强,则使用 org.aspectj.lang.ProceedingJoinPoint 表示连接点对象,ProceedingJoinPoint 类是 JoinPoint 的子接口。
(1) JoinPoint 接口的主要方法:
- java.lang.Object[] getArgs():获取连接点方法运行时的入参列表;
- Signature getSignature():获取连接点的方法签名对象;
- java.lang.Object getTarget():获取连接点所在的目标对象;
- java.lang.Object getThis():获取代理对象本身;
(2) ProceedingJoinPoint:
除了继承上述四个方法外,还新增了两个:
- java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法;
- java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法,不过使用新的入参替换原来的入参。
下面通过具体的实例来看一下每个方法的用法。
这里我们采用JDK代理的方式,首先定义一个接口,
package com.dz.demo.aspect;
/**
* Created by dzwang on 2019/3/6.
*/
public interface Humanity {
void speckTo(String name, String words);
void walkTo(String place);
}
它的实现类为:
package com.dz.demo.aspect;
/**
* Created by dzwang on 2019/3/6.
*/
public class Man implements Humanity {
public void speckTo(String name, String words) {
System.out.println("speckTo " + name + ": " + words);
}
public void walkTo(String place) {
System.out.println("walkTo " + place);
}
}
基础工作完成好了之后,我们实现一个切面,增强方法的第一个入参声明为 org.aspectj.lang.ProceedingJoinPoint 类型:
package com.dz.demo.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
/**
* Created by dzwang on 2019/3/6.
*/
@Aspect
public class TestAspect {
@Around("execution(* speckTo(..)) && target(com.dz.demo.aspect.Man)")
public void testJoinPoint(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("****testJoinPoint start****");
System.out.println("getArgs():" + pjp.getArgs());
System.out.println("Arg0:" + pjp.getArgs()[0]);
System.out.println("getSignature():" + pjp.getSignature().getName());
System.out.println("getTarget():" + pjp.getTarget().getClass());
System.out.println("getThis():" + pjp.getThis().toString());
pjp.proceed();
System.out.println("****testJoinPoint end****");
}
}
定义好 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"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.dz.demo.aspect">
</context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
<bean id="man" class="com.dz.demo.aspect.Man"></bean>
<bean class="com.dz.demo.aspect.TestAspect"></bean>
</beans>
最后,写测试方法来看看 JoinPoint 类中各个方法的具体用途:
package com.dz.demo.aspect;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created by dzwang on 2019/3/6.
*/
public class StartDemo {
public static void main(String[] args) {
String configPath = "classpath:beans.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configPath);
Humanity man = (Humanity) context.getBean("man");
man.speckTo("Dennis", "Hello");
man.walkTo("Company");
}
}
输出结果如下:
****testJoinPoint start****
getArgs():[Ljava.lang.Object;@4c178a76
Arg0:Dennis
getSignature():speckTo
getTarget():class com.dz.demo.aspect.Man
getThis():com.dz.demo.aspect.Man@4988d8b8
speckTo Dennis: Hello
****testJoinPoint end****
walkTo Company