I am trying to call a method asynchronously. But somehow it doesn't work. Could someone please help me resolve this issue?
My main entry point:
@SpringBootApplication
@EnableAsync
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
AsyncService asyncService = new AsyncService();
asyncService.asyncMethod();
asyncService.asyncMethod();
}
}
Async Service:
@Component
public class AsyncService {
@Async
public void asyncMethod(){
log.info("starting...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("ending...");
}
}
And finally, in log I am expecting:
but this is what I get:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.2.RELEASE)
2019-02-13 17:52:41.548 INFO 85734 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication on mntbden00122972 with PID 85734 (/Users/h3560/demo/target/classes started by h3560 in /Users/h3560/demo)
2019-02-13 17:52:41.550 INFO 85734 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
2019-02-13 17:52:42.084 INFO 85734 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 0.76 seconds (JVM running for 1.329)
2019-02-13 17:52:42.086 INFO 85734 --- [ main] com.example.demo.services.AsyncService : starting...
2019-02-13 17:52:44.088 INFO 85734 --- [ main] com.example.demo.services.AsyncService : ending...
2019-02-13 17:52:44.089 INFO 85734 --- [ main] com.example.demo.services.AsyncService : starting...
2019-02-13 17:52:46.091 INFO 85734 --- [ main] com.example.demo.services.AsyncService : ending...
@Async
is spring's annotation that is being applied to public
methods on proxies (that's why they need to be public). Self invocation does not work.
In your example, you are not using dependency injection mechanism from spring, so no proxy is being created. To bypass it, you need to make a @Bean
out of it (which you have done by annotating it with @Component
) and @Autowire
it before execution:
@SpringBootApplication
@EnableAsync
public class DemoApplication {
@Autowired
AsyncService asyncService;
public someMethod() {
SpringApplication.run(DemoApplication.class, args);
asyncService.asyncMethod();
asyncService.asyncMethod();
}
}
With this spring AOP can wrap the component into proxy and execute the method asynchronously.
The issue you're having is with instantiating the object manually via the new
operator. This does not give the framework the opportunity to wrap the object in proxies. If you want to use the Asynchronous methods you have to use Spring DI by Factory Methos, @Autowired
(or @Inject
) or using XML configurations.
If you do it like that, you can make System.out.println(obj.getClass())
, to see, that under the hood beans injected with DI are not of the class you used there, but of a proxy one.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.