NoClassDefFoundError(MainMethodRunner.java:53
我正在开发AOP记录器。它可以在带有main()方法的直接Java类中正常工作,但在与Spring Boot结合使用时会失败。日志jar文件位于bootclasspath和类路径中。即使在我能够打印出类路径之前,也会抛出异常。我错过了一个让Spring Boot开心的配置步骤吗?
例外:
java.lang.reflect.InvocationTargetException
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:483)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.co.brs.logging.aop.AopLogger
at com.co.brs.restserver.RestApplication.main(RestApplication.java:73)
... 6 more
命令行:
/usr/java/latest/bin/java -Xbootclasspath/p:/usr/local/co/lib/logging-logger.jar -server -cp /usr/local/co/lib/logging-logger.jar:/usr/local/co/bin/../lib/restserver:/usr/local/co/lib/*:/usr/local/co/catalog/lib/*:/usr/local/co/lib/logging-logmanager/* -jar /usr/local/co/bin/../lib/restserver/rest-server.jar >> /usr/local/co/bin/../log/restserver.out 2>&1 &
RestApplication.java:
@Configuration
@EnableAutoConfiguration
@ComponentScan({"com.co.brs.restserver.component", "com.co.brs.restserver.service", "com.co.brs.restserver.web", "com.co.brs.restserver.doc"})
public class RestApplication {
@Value("${keystore.file}") private String keystoreFile;
@Value("${keystore.pass}") private String keystorePass;
@Value("${keystore.type}") private String keystoreType;
@Value("${secure.port}") private String securePort;
/**
* Start Spring boot Application
* @throws Exception
*/
public static void main(String[] args) throws Exception {
ClassLoader loader = RestApplication.class.getClassLoader();
System.out.println(System.getProperty("java.class.path"));
//Get the System Classloader
ClassLoader sysClassLoader = ClassLoader.getSystemClassLoader();
//Get the URLs
URL[] urls = ((URLClassLoader)sysClassLoader).getURLs();
for(int i=0; i< urls.length; i++)
{
System.out.println(urls[i].getFile());
}
SpringApplication restApp = new SpringApplication(RestApplication.class);
restApp.setShowBanner(false);
restApp.setDefaultProperties(new HashMap<String, Object>());
ApplicationContext context = restApp.run(args);
RestService restService = context.getBean(RestService.class);
restApp.setRegisterShutdownHook(true);
// Start component
if (!restService.start()) {
// Failed to start
System.out.println("Failed to start - exiting\n");
System.exit(SpringApplication.exit(context, new JobExecutionExitCodeGenerator()));
}
System.out.println("Rest Service is up and running");
}
AOP Logger片段:
pointcut logMethod():
(execution(public * *(..)) && !execution(public * get*(..)) && !execution(public void set*(..))
&& !cflow(adviceexecution() && !execution(public com.co.brs.logging* *(..))));
before(): logMethod() {...}
pom.xml文件包含以下依赖项:
<dependency>
<groupId>com.co.brs.logging</groupId>
<artifactId>logging-logger</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.2</version>
</dependency>
和
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
我更新了AOPLogger中的切入点以忽略main()方法,并且进一步了解。
切入点:
pointcut logMethod():
(execution(public * *(..)) && !execution(public * get*(..)) && !execution(public void set*(..)) && !execution(public void main(..))
&& !cflow(adviceexecution() && !execution(public com.co.brs.logging* *(..))));
新输出:(代码进入执行:
java.lang.reflect.InvocationTargetException
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:483)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoClassDefFoundError: org/aspectj/runtime/reflect/Factory
at com.co.brs.logging.CatalogHandler.ajc$preClinit(CatalogHandler.java:1)
at com.co.brs.logging.CatalogHandler.<clinit>(CatalogHandler.java:1)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at java.lang.Class.newInstance(Class.java:433)
at java.util.logging.LogManager$5.run(LogManager.java:966)
at java.security.AccessController.doPrivileged(Native Method)
at java.util.logging.LogManager.loadLoggerHandlers(LogManager.java:958)
at java.util.logging.LogManager.initializeGlobalHandlers(LogManager.java:1578)
at java.util.logging.LogManager.access$1500(LogManager.java:145)
at java.util.logging.LogManager$RootLogger.accessCheckedHandlers(LogManager.java:1667)
at java.util.logging.Logger.getHandlers(Logger.java:1776)
at org.slf4j.bridge.SLF4JBridgeHandler.removeHandlersForRootLogger(SLF4JBridgeHandler.java:169)
at org.springframework.boot.logging.log4j.Log4JLoggingSystem.beforeInitialize(Log4JLoggingSystem.java:64)
at org.springframework.boot.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:135)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:98)
at org.springframework.boot.context.event.EventPublishingRunListener.publishEvent(EventPublishingRunListener.java:100)
at org.springframework.boot.context.event.EventPublishingRunListener.started(EventPublishingRunListener.java:54)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:276)
at com.emc.brs.restserver.RestApplication.main(RestApplication.java:62)
... 6 more
答案 0 :(得分:0)
我进一步更新了切入点,只包含了我的产品包,现在代码已经过了初始启动而没有问题。最后的切入点定义了我的包的拦截,而不是简单的getter和setter,而不是日志包本身,而不是main()方法,而不是在提供建议时。
pointcut logMethod():
(execution(public com.co.brs* *(..))
&& !execution(public * get*(..))
&& !execution(public void set*(..))
&& !execution(public void main(..))
&& !cflow(adviceexecution()
&& !execution(public com.co.brs.logging* *(..))));
before(): logMethod()
{ ... }
答案 1 :(得分:0)
对我而言,您似乎希望捕获某个包中的公共方法调用,而不是从该包返回类型的方法调用,即execution(public * com.co.brs..*(..))
而不是execution(public com.co.brs..* *(..))
。对于最后的日志执行也是如此,你也错了。
您还可以进一步优化切入点,例如由
com.co.brs..*
之类的结构代替com.co.brs*
明确表示您的意思是包com.co.brs
及其所有子包public
链接在一起的后续切入点上省略&&
修饰符,因为第一个切入点已经将执行限制为公共切入点。pointcut logMethod():
execution(public * com.co.brs..*(..)) &&
!execution(* get*(..)) &&
!execution(void set*(..)) &&
!execution(void main(..)) &&
!cflow(adviceexecution()) &&
!execution(* com.co.brs.logging..*(..));
请注意!cflow(adviceexecution())
也不包括从其他方面执行其他建议。如果这是你想要的,那很好。如果没有,您应该使用类似!within(MyAdvice)
的内容。