Spring-boot: exposeProxy = true not in effect

Created on 11 Apr 2019  ·  18Comments  ·  Source: spring-projects/spring-boot

Sorry, my English is not very good.

describe:
I use @EnableAspectJAutoProxy(exposeProxy = true),but I can not get the current AOP proxy by AopContex.currentProxy().

environment:
Spring Boot (2.1.4.RELEASE).

There are only two classes of this project:

@SpringBootApplication
@EnableAsync
@EnableAspectJAutoProxy(exposeProxy = true)
public class DemoTest2Application {

    public static void main(String[] args) {
        SpringApplication.run(DemoTest2Application.class, args);
    }
}
@Controller
public class EmailController {

    @RequestMapping(value = "/test", method = RequestMethod.GET)
    @ResponseBody
    public Object asyncCall() throws InterruptedException {
        System.out.println("before....");
        ((EmailController) AopContext.currentProxy()).testAsyncTask();
        System.out.println("after....");
        return "OK";
    }


    @Async
    public void testAsyncTask() throws InterruptedException {
        Thread.sleep(10000);
        System.out.println("异步任务执行完成!");
    }
    }

when I request "localhost:8080/test" .I get exception:

java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.
    at org.springframework.aop.framework.AopContext.currentProxy(AopContext.java:69) ~[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE]

Looking through all kinds of documents, I don't know where I was wrong.

external-project invalid

All 18 comments

@dongguabai interesting, that's probably because Spring Boot auto-configures this already. Can you please add spring.aop.auto=false to your app and check if that fixes the problem?

@dongguabai interesting, that's probably because Spring Boot auto-configures this already. Can you please add spring.aop.auto=false to your app and check if that fixes the problem?

@snicoll
Thank you for your reply.
I add spring.aop.auto=false ,but the problem is still unsolved.

((EmailController) AopContext.currentProxy()).testAsyncTask();这个方法必须要获得当前代理类啊,但是你的testAsyncTask()并没有使用到切面之类的东西,所以就获取不到当前方法的代理类了。。你需要在方法上加上@Transactional之类会形成切面的东西。让他代理到AOP

((EmailController) AopContext.currentProxy()).testAsyncTask();这个方法必须要获得当前代理类啊,但是你的testAsyncTask()并没有使用到切面之类的东西,所以就获取不到当前方法的代理类了。。你需要在方法上加上@transactional之类会形成切面的东西。让他代理到AOP

但是 testAsyncTask() 使用了 @Async 注解啊

没用过@async注解,你看看这个注解的实现是用的aop吗?好像不是吧,没有使用到AOP在AOP的上下文就获取不到的吧。

没用过@async注解,你看看这个注解的实现是用的aop吗?好像不是吧,没有使用到AOP在AOP的上下文就获取不到的吧。

本质用的就是 AOP

I'm also facing the same issue.

As far as I can tell, there's nothing to tie together the exposeProxy setting on @EnableAspectJAutoProxy with the proxy creation that's done as a result of @EnableAsync. The latter has its own proxy-related attributes but does not have one for proxy exposure. This results in AnnotationAwareAspectJAutoProxyCreator having its exposeProxy property set to true and AsyncAnnotationBeanPostProcessor (which creates proxies for classes with @Async methods) having its exposeProxy property with the default value of false.

What should we do to change the ExposeProxy property of AsyncAnnotationBeanPostProcessor

@dngzs Set the exposeProxy attribute when you add @EnableAsync to your application.

sorry,Can you be more specific? ProxyAsyncConfiguration is not set, how can I cover it?

@Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
    Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
    AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
    Class<? extends Annotation> customAsyncAnnotation = enableAsync.getClass("annotation");
    if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
        bpp.setAsyncAnnotationType(customAsyncAnnotation);
    }
    if (this.executor != null) {
        bpp.setExecutor(this.executor);
    }
    if (this.exceptionHandler != null) {
        bpp.setExceptionHandler(this.exceptionHandler);
    }
    bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
    bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
    return bpp;
}

I am sorry for your work time.

Sorry, I answered too hastily. As I'd already noted above there's no such attribute on @EnableAsync.

The code you have quoted above is part of Spring Framework rather than Spring Boot. If you would like to be able to configure the AsyncAnnotationBeanPostProcessor that is created to expose the proxies that it creates, please open a Spring Framework enhancement request.

Thank you very much for your answer, delay your precious time.

    @Resource
    private AsyncAnnotationBeanPostProcessor asyncAdvisor;

    @PostConstruct
    private void init(){
        asyncAdvisor.setExposeProxy(true);
    }
    @Resource
    private AsyncAnnotationBeanPostProcessor asyncAdvisor;

    @PostConstruct
    private void init(){
        asyncAdvisor.setExposeProxy(true);
    }

This is not particularly well written. Every class that is being delegated needs to be written. If you want to be global, you can implement BeanPostProcessor and PriorityOrdered to set AsyncAnnotationBeanPostProcessor before AsyncAnnotationBeanPostProcessor. This is globally common, of course, this is just a kind of the way

这样写不是特别好,每个被代理的类都需要这么写,如果你想全局生效,你可以实现BeanPostProcessor和PriorityOrdered 去在AsyncAnnotationBeanPostProcessor 之前设置处理AsyncAnnotationBeanPostProcessor ,这样就全局通用了,当然这仅仅只是一种方式

it seems adding @EnableAspectJAutoProxy(exposeProxy = true) to the actual bean works

As noted above this needs to be addressed via an enhancement to Spring Framework.

this works for me, set the property manually

@Component
public class AsyncBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition(org.springframework.scheduling.config.TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME);
        beanDefinition.getPropertyValues().add("exposeProxy", true);
    }
}
Was this page helpful?
0 / 5 - 0 ratings