Spring 如何获取 AOP 代理类的实际对象 Class

发布于 2022-05-17
在使用 Spring 时,如果对某个 Spring Bean (*下文简称 Bean*) 使用了 AOP,那么调用 bean.getClass()时获取到的是代理对象,当我们想对 Bean 做一些反射操作时,使用代理对象是会出错的。Spring AOP 包中提供了一个工具类可以获取到原始对象的 Class: Ao…

在使用 Spring 时,如果对某个 Spring Bean (下文简称 Bean) 使用了 AOP,那么调用 bean.getClass()时获取到的是代理对象,当我们想对 Bean 做一些反射操作时,使用代理对象是会出错的。Spring AOP 包中提供了一个工具类可以获取到原始对象的 Class: AopUtils.getTargetClass

如有 Bean:

@Service
public class UserService {

	public void test() {
		System.out.println("test");
	}

}

AOP 切面:

@Aspect
@Component
public class MyAop {

    /**
     * 切入点
     */
    @Pointcut("execution(public * im.zhaojun.blog.code.service.*.*(..))")
    public void pointcut(){
    }

    /**
     * 前置通知
     */
    @Before("pointcut()")
    public void deBefore(JoinPoint jp) {
        System.out.println("before");
    }

}

测试类:

@SpringBootTest
class BlogCodeDemoApplicationTests {

	@Resource
	private UserService userService;

	@Test
	void contextLoads() {
		Class<? extends UserService> proxyServiceClass = userService.getClass();
		Class<?> serviceClass = AopUtils.getTargetClass(userService);
		System.out.println("代理类:" + proxyServiceClass);
		System.out.println("实际类:" + serviceClass);

		System.out.println("代理类方法个数:" + proxyServiceClass.getMethods().length);
		System.out.println("实际类方法个数:" + serviceClass.getMethods().length);
	}

}

输出为, 经测试结果可见,如果想要对 AOP 后的 Bean 进行反射,需要使用原始对象:

代理类:class im.zhaojun.blog.code.service.UserService$$EnhancerBySpringCGLIB$$a0f386db
实际类:class im.zhaojun.blog.code.service.UserService
代理类方法个数:44
实际类方法个数:10

1652410317394.png