springboot启动报sun.reflect.annotation.TypeNotPresentExceptionProxy

今天启动一个springboot的应用时,报了一个TypeNotPresentExceptionProxy,而且里面的堆栈信息没有一个是自己的业务代码,这就头疼了。

11:17:55.215 "restartedMain" INFO  "" "" "" com.heytea.service.coupon.ServiceCouponApplication The following profiles are active: develop
11:17:56.794 "restartedMain" INFO  "" "" "" org.springframework.data.repository.config.RepositoryConfigurationDelegate Multiple Spring Data modules found, entering strict repository configuration mode!
11:17:56.796 "restartedMain" INFO  "" "" "" org.springframework.data.repository.config.RepositoryConfigurationDelegate Bootstrapping Spring Data Redis repositories in DEFAULT mode.
11:17:56.832 "restartedMain" INFO  "" "" "" org.springframework.data.repository.config.RepositoryConfigurationDelegate Finished Spring Data repository scanning in 25ms. Found 0 Redis repository interfaces.
11:17:56.986 "restartedMain" WARN  "" "" "" org.springframework.boot.actuate.endpoint.EndpointId Endpoint ID 'service-registry' contains invalid characters, please migrate to a valid format.
11:17:57.095 "restartedMain" WARN  "" "" "" org.springframework.boot.actuate.endpoint.EndpointId Endpoint ID 'hystrix.stream' contains invalid characters, please migrate to a valid format.
11:18:22.295 "Apollo-RemoteConfigLongPollService-1" WARN  "" "" "" com.ctrip.framework.apollo.internals.RemoteConfigLongPollService Long polling failed, will retry in 1 seconds. appId: 100003012, cluster: dev-mb-1, namespaces: application+common-config, long polling url: http://10.22.64.3:8080/notifications/v2?cluster=dev-mb-1&dataCenter=dev-mb-1&appId=100003012&ip=10.250.210.215&notifications=%5B%7B%22namespaceName%22%3A%22application%22%2C%22notificationId%22%3A52%7D%2C%7B%22namespaceName%22%3A%22common-config%22%2C%22notificationId%22%3A139%7D%5D, reason: java.io.IOException: Server returned HTTP response code: 502 for URL: http://10.22.64.3:8080/notifications/v2?cluster=dev-mb-1&dataCenter=dev-mb-1&appId=100003012&ip=10.250.210.215&notifications=%5B%7B%22namespaceName%22%3A%22application%22%2C%22notificationId%22%3A52%7D%2C%7B%22namespaceName%22%3A%22common-config%22%2C%22notificationId%22%3A139%7D%5D [Cause: Server returned HTTP response code: 502 for URL: http://10.22.64.3:8080/notifications/v2?cluster=dev-mb-1&dataCenter=dev-mb-1&appId=100003012&ip=10.250.210.215&notifications=%5B%7B%22namespaceName%22%3A%22application%22%2C%22notificationId%22%3A52%7D%2C%7B%22namespaceName%22%3A%22common-config%22%2C%22notificationId%22%3A139%7D%5D [Cause: Server returned HTTP response code: 502 for URL: http://10.22.64.3:8080/notifications/v2?cluster=dev-mb-1&dataCenter=dev-mb-1&appId=100003012&ip=10.250.210.215&notifications=%5B%7B%22namespaceName%22%3A%22application%22%2C%22notificationId%22%3A52%7D%2C%7B%22namespaceName%22%3A%22common-config%22%2C%22notificationId%22%3A139%7D%5D]]
11:18:22.309 "restartedMain" ERROR "" "" "" org.springframework.boot.SpringApplication Application run failed
java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy
	at sun.reflect.annotation.AnnotationParser.parseClassArray(AnnotationParser.java:724)
	at sun.reflect.annotation.AnnotationParser.parseArray(AnnotationParser.java:531)
	at sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:355)
	at sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:286)
	at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:120)
	at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:72)
	at java.lang.reflect.Executable.declaredAnnotations(Executable.java:599)
	at java.lang.reflect.Executable.declaredAnnotations(Executable.java:597)
	at java.lang.reflect.Executable.getDeclaredAnnotations(Executable.java:588)
	at java.lang.reflect.Method.getDeclaredAnnotations(Method.java:630)
	at org.springframework.core.annotation.AnnotationsScanner.getDeclaredAnnotations(AnnotationsScanner.java:499)
	at org.springframework.core.annotation.AnnotationsScanner.isKnownEmpty(AnnotationsScanner.java:543)
	at org.springframework.core.annotation.TypeMappedAnnotations.from(TypeMappedAnnotations.java:251)
	at org.springframework.core.annotation.MergedAnnotations.from(MergedAnnotations.java:329)
	at org.springframework.core.annotation.AnnotatedElementUtils.findAnnotations(AnnotatedElementUtils.java:764)
	at org.springframework.core.annotation.AnnotatedElementUtils.hasAnnotation(AnnotatedElementUtils.java:531)
	at org.springframework.context.annotation.BeanAnnotationHelper.isBeanAnnotated(BeanAnnotationHelper.java:41)
	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.isMatch(ConfigurationClassEnhancer.java:407)
	at org.springframework.context.annotation.ConfigurationClassEnhancer$ConditionalCallbackFilter.accept(ConfigurationClassEnhancer.java:192)
	at org.springframework.cglib.proxy.Enhancer.emitMethods(Enhancer.java:1217)
	at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:726)
	at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
	at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
	at org.springframework.cglib.core.ClassLoaderAwareGeneratorStrategy.generate(ClassLoaderAwareGeneratorStrategy.java:57)
	at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:358)
	at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:585)
	at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:110)
	at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108)
	at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
	at java.util.concurrent.FutureTask.run(FutureTask.java)
	at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
	at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
	at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:134)
	at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:319)
	at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:572)
	at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:419)
	at org.springframework.context.annotation.ConfigurationClassEnhancer.createClass(ConfigurationClassEnhancer.java:137)
	at org.springframework.context.annotation.ConfigurationClassEnhancer.enhance(ConfigurationClassEnhancer.java:109)
	at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:423)
	at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurationClassPostProcessor.java:257)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:291)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:131)
	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:707)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:533)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
	at com.heytea.service.coupon.ServiceCouponApplication.main(ServiceCouponApplication.java:27)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Disconnected from the target VM, address: '127.0.0.1:62642', transport: 'socket'
Process finished with exit code 0


上网一查,每个人的情况可能都不一样。不过idea还是智能,提醒我们可以在这个异常里面打断点

create breakpoint

那我们就在这个异常里面打两个端点

操作下来发现这里抛的异常sun.reflect.annotation.AnnotationParser#parseClassValue

其实是class Not Found,而且也明确了是哪个类找不到。比如报的是XXConfiguration里面的RabbitListener不存在。

@Configuration
@ConditionalOnProperty(
    name = {"xx.enabled"},
    havingValue = "true",
    matchIfMissing = true
public class XXConfiguration {
    @Bean
    @ConditionalOnClass(RabbitListener.class)
    public RoutingTagRabbitMqAspect routingTagRabbitMqAspect(){
        return new RoutingTagRabbitMqAspect(routingTag);
}

说明一下,我们是写了一个公共的starter,里面有XXConfiguration,然后定义了一个mq的拦截器,在starter里面依赖的mq是optional。

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-amqp</artifactId>
			<optional>true</optional>
		</dependency>

其他业务工程依赖这个starter,不会继承spring-boot-starter-amqp,所以一启动就会报错。

问题来了,ConditionalOnClass不就是判断class是否存在来创建bean吗,为什么还会报错?

看一下这个类的javadoc。

/**
 * {@link Conditional @Conditional} that only matches when the specified classes are on
 * the classpath.
 * A {@link #value()} can be safely specified on {@code @Configuration} classes as the
 * annotation metadata is parsed by using ASM before the class is loaded. Extra care is
 * required when placed on {@code @Bean} methods, consider isolating the condition in a
 * separate {@code Configuration} class, in particular if the return type of the method
 * matches the {@link #value target of the condition}.
 * @author Phillip Webb
 * @since 1.0.0
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {
	 * The classes that must be present. Since this annotation is parsed by loading class
	 * bytecode, it is safe to specify classes here that may ultimately not be on the
	 * classpath, only if this annotation is directly on the affected component and
	 * <b>not</b> if this annotation is used as a composed, meta-annotation. In order to
	 * use this annotation as a meta-annotation, only use the {@link #name} attribute.
	 * @return the classes that must be present
	Class<?>[] value() default {};