Proguard+spring boot fails to start injection after multi-module confusion, reporting NoSuchBeanDefinitionException, UnsatisfiedDependencyException error

1. Problem description

In the spring boot multi-module project, one of the modules, after being confused with proguard, is introduced in the main module, and the following error is reported when it starts:

19:46:30.729 [main] ERROR o.s.b.SpringApplication - [reportFailure,860] - Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jobHandlerBeanPostProcessor' defined in class path resource [com/xxx/xxx/xxx/config/xxxxJobAutoConfiguration.class]: Unsatisfied dependency expressed through method 'jobHandlerBeanPostProcessor' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.xxx.xxx.xxx.service.LesseeFrameworkService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {
    
    }
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:541)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:270)
	at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:762)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:567)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:771)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:763)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:438)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:339)
	at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:144)
	at com.xxx.xxx.modules.admin.AdminStartApplication.execute(AdminStartApplication.java:220)
	at com.xxx.xxx.modules.admin.AdminStartApplication.start(AdminStartApplication.java:125)
	at com.xxx.xxx.modules.admin.AdminStartApplication.main(AdminStartApplication.java:67)
	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.loader.MainMethodRunner.run(MainMethodRunner.java:48)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
	at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.xxx.xxx.xxx.service.LesseeFrameworkService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {
    
    }
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1790)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1346)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
	... 29 common frames omitted
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jobHandlerBeanPostProcessor' defined in class path resource [com/xxx/xxx/xxx/config/xxxxJobAutoConfiguration.class]: Unsatisfied dependency expressed through method 'jobHandlerBeanPostProcessor' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.xxx.xxx.xxx.xxx.service.LesseeFrameworkService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {
    
    }
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:541)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:270)
	at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:762)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:567)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:771)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:763)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:438)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:339)
	at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:144)
	at com.xxx.xxx.modules.admin.AdminStartApplication.execute(AdminStartApplication.java:220)
	at com.xxx.xxx.modules.admin.AdminStartApplication.start(AdminStartApplication.java:125)
	at com.xxx.xxx.modules.admin.AdminStartApplication.main(AdminStartApplication.java:67)
	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.loader.MainMethodRunner.run(MainMethodRunner.java:48)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
	at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.xxx.xxx.xxx.service.LesseeFrameworkService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {
    
    }
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1790)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1346)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)

NoSuchBeanDefinitionException, UnsatisfiedDependencyException This kind of error means that the injection fails, and the relevant bean is not found, and the error will be reported

Two, the solution

, after the event is solved, the summary is as follows, and the investigation can be performed as follows:

1. Do not confuse the annotations related to spring. Once confused, this situation is easy to occur. Configure the following options:

# 不混淆所有特殊的类:对异常、注解信息在runtime予以保留,不然影响springboot启动
-keepattributes Exceptions,InnerClasses,Signature?Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,SyntheticjEnclosingMethod

-keepclassmembers class * {
    
    
     @org.springframework.beans.factory.annotation.Autowired *;
     @org.springframework.beans.factory.annotation.Qualifier *;
     @org.springframework.beans.factory.annotation.Value *;
     @org.springframework.beans.factory.annotation.Required *;
     @org.springframework.context.annotation.Bean *;
     @org.springframework.context.annotation.Primary *;
     @org.springframework.boot.context.properties.ConfigurationProperties *;
     @org.springframework.boot.context.properties.EnableConfigurationProperties *;
     @javax.inject.Inject *;
     @javax.annotation.PostConstruct *;
     @javax.annotation.PreDestroy *;
}
-keepclassmembers class * {
    
    
     @org.springframework.beans.factory.annotation.Autowired <fields>;
     @org.springframework.beans.factory.annotation.Autowired <methods>;
     @org.springframework.security.access.prepost.PreAuthorize <methods>;
}

2. After confusion, confirm whether your package name has been changed, and you need to add it if you change it

@ComponentScan(value = {
    
    "com.xxx","xxx.xxx.xxx"})

3.jar problem, proguard needs to maintain the directory structure

#保持目录结构
-keepdirectories

Otherwise, it will appear, and it will be empty in the following way:

this.getClassLoader("com/xxxx/xxx")

This is where I report the error. In the packaged \BOOT-INF\lib directory, there are obviously dependent jars and class files, which is the above error. From the log stack information, combined with the source code, I found it in org.springframework .context.annotation.ClassPathScanningCandidateComponentProvider in the scanCandidateComponents in the ClassPathScanningCandidateComponentProvider class
insert image description here
converts the configured package name into a path form, go to classpath*: to find, in line 421, the jar package of the bean that reported the error cannot be found, copy the code out , create a new test class:

        //获取Spring资源解析器
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        //获取packageSearchPath下的Resource,这里得到的Resource是Class信息
        Resource[] resources = resourcePatternResolver.getResources("com.xxx.xxx"
                + ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage))
                + DEFAULT_RESOURCE_PATTERN + ClassUtils.CLASS_FILE_SUFFIX);
        Arrays.stream(resources).forEach(resource -> {
    
    
            System.out.println("=======>" + resource.getFilename());
        });

The acquisition is also empty. Using ClassGraph, it can be obtained in the form of package name

        try (ScanResult scanResult = new ClassGraph().acceptPackages("com.xxx.xxx.xxx").scan()) {
    
    
            scanResult.getAllResources().forEachByteArrayIgnoringIOException((io.github.classgraph.Resource res, byte[] content) -> {
    
    
                String path = res.getPath();
                System.out.println("文件:" + path);
            });
        }

Test step by step, manually decompress the jar package, and then package the jar through the jar command

jar -cfM0 xxx.jar .

It is OK to re-package. I am sure it is the cause of the jar package. I suspect that there may be a problem with the jar package directory. It seems that there is no problem with the compression software, and then print the jar package directory through the following code, and there is no problem.

        JarFile startJarFile = new JarFile("E:\\xxx\\start-1.0-SNAPSHOT.jar");
        Enumeration<JarEntry> startJarEntrys = startJarFile.entries();
        while (startJarEntrys.hasMoreElements()) {
    
    
            JarEntry entry = startJarEntrys.nextElement();
            System.out.println("startJarEntrys:" + entry.getName());
        }

Go to the Internet to find the jar package format. . . It is related to the introduction of the MAINFEST.MF file. . Finally, through the 7zip command, it was found that there was indeed a problem with the directory of the jar package:

7z l xxxx.jar

Wrong jar package directory:

insert image description here

The correct jar package directory:
insert image description here

Guess you like

Origin blog.csdn.net/mashangzhifu/article/details/123112631