org.springframework.boot.loader.MainMethodRunner.run中的NoClassDefFoundError(MainMethodRunner.java:53

时间:2014-10-08 18:13:33

标签: aop spring-boot

org.springframework.boot.loader.MainMethodRunner.run中的

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

2 个答案:

答案 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)的内容。