For example:
@Before(value = "execution(* org.springframework.cloud.client.serviceregistry.ServiceRegistry.register(*)) && target(registry) && args(registration)", argNames = "registry, registration")
org.springframework.cloud.consul.serviceregistry.ServiceRegistry
is an interface.
In JVM the code is OK, but it does not work built with native-image (Spring 6.0.11), unless I change it to:
@Before(value = "execution(* org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry.register(*)) && target(registry) && args(registration)", argNames = "registry, registration")
Comment From: sbrannen
I imagine you'll need to register runtime hints for ConsulServiceRegistry
so that it can be determined via reflection within a native image that it implements ServiceRegistry
.
See if that line of thinking helps you resolve the issue.
If not, please provide a minimal example application that we can run ourselves -- preferably a public Git repository or a ZIP file attached to this issue.
Comment From: imgoby
this is the project: https://github.com/imgoby/spring-cloud-alibaba-graalvm/tree/main/spring-cloud-alibaba-consul-dubbo-provider
its dependency is https://github.com/imgoby/spring-cloud-alibaba-graalvm/tree/main/spring-cloud-alibaba-starter-dubbo
The relevant class is this: https://github.com/imgoby/spring-cloud-alibaba-graalvm/blob/main/spring-cloud-alibaba-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboServiceRegistrationEventPublishingAspect.java
/**
* The pointcut expression for {@link ServiceRegistry#register(Registration)}.
*/
public static final String REGISTER_POINTCUT_EXPRESSION = "execution(* org.springframework.cloud.client.serviceregistry.ServiceRegistry.register(*)) && target(registry) && args(registration)";
/**
* The pointcut expression for {@link ServiceRegistry#deregister(Registration)}.
*/
public static final String DEREGISTER_POINTCUT_EXPRESSION = "execution(* org.springframework.cloud.client.serviceregistry.ServiceRegistry.deregister(*)) && target(registry) && args(registration)";
I'm trying to modify it to an implementation class.So, some codes were changed to :
public static final String REGISTER_POINTCUT_EXPRESSION_CONSUL = "execution(* org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry.register(*)) && target(registry) && args(registration)";
Comment From: imgoby
I imagine you'll need to register runtime hints for
ConsulServiceRegistry
so that it can be determined via reflection within a native image that it implementsServiceRegistry
.See if that line of thinking helps you resolve the issue.
If not, please provide a minimal example application that we can run ourselves -- preferably a public Git repository or a ZIP file attached to this issue.
Yes, the runtime class maybe ConsulServiceRegistry or EurekaServiceRegistry or NacosServiceRegistry or ZookeeperServiceRegistry.It is defined by user configuration
Comment From: imgoby
I understand a bit now. I may need to make the necessary modifications like this
@Configuration
@ConditionalOnBean(name = "org.springframework.cloud.client.serviceregistry.ServiceRegistry")
@Aspect
public class ConsulAspect{}
@Configuration
@ConditionalOnBean(name = "org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry")
@Aspect
public class EurekaAspect{}
Comment From: imgoby
Is that right?
Comment From: sbrannen
I don't think @ConditionalOnBean
will provide any benefit for the scenario you're encountering.
Rather, I was saying I think you'll need to register runtime hints for the use of reflection (for evaluating your AspectJ pointcut expression) within a GraalVM native image.
Comment From: sbrannen
Potentially related issues:
-
28711
-
30529
Comment From: imgoby
Can you provide some sample code?
Comment From: imgoby
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportRuntimeHints;
@SpringBootApplication
@EnableDiscoveryClient
@EnableDubbo
@ImportRuntimeHints(ProviderApplication.ServiceRegistryRuntimeHints.class)
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
static class ServiceRegistryRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
hints.reflection().registerType(org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry.class,
MemberCategory.values());
}
}
}
Is this OK?But I should write the final implement class in my code.
Comment From: sbrannen
Is this OK?
Yes, I was suggesting something like that.
Though, I don't think you need to register all MemberCategory
values to get it to work.
In any case, can you please confirm that ServiceRegistryRuntimeHints
allows your aspect to work properly in a native image?
But I should write the final implement class in my code.
I don't understand what you mean by that. Can you please expound?
Comment From: imgoby
Is this OK?
Yes, I was suggesting something like that.
Though, I don't think you need to register all
MemberCategory
values to get it to work.In any case, can you please confirm that
ServiceRegistryRuntimeHints
allows your aspect to work properly in a native image?But I should write the final implement class in my code.
I don't understand what you mean by that. Can you please expound?
Previously, it was just an interface called org. springframework. cloud. client. serviceregistry.ServiceRegistry,and there are several implementation classes,such as org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry.class, org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry
Is it written here as follow? hints.reflection().registerType(org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry.class, MemberCategory.values()); hints.reflection().registerType(org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry.class, MemberCategory.values());
Comment From: imgoby
This is the file I want to modify, even if I use RuntimeHintsRegistry, @Before will not be triggered.
https://github.com/imgoby/spring-cloud-alibaba-graalvm/blob/main/spring-cloud-alibaba-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboServiceRegistrationEventPublishingAspect.java
Is something wrong?
Comment From: imgoby
@ImportRuntimeHints is not working in my project and the issue cannot be resolved. Therefore, I divided the original classes into four. The project is now working normally.
https://github.com/imgoby/spring-cloud-alibaba-graalvm/blob/main/spring-cloud-alibaba-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboServiceRegistrationEventPublishingAspect.java