【问题标题】:Compile Time Weaving Null Pointer Exception编译时编织空指针异常
【发布时间】:2013-02-23 23:44:55
【问题描述】:

编辑 7:

问题似乎是如何让@ConfigurableHttpSessionListener 一起工作,建议了一种解决方法,但我不想直接与WebApplicationContext 交互:

   @Configurable(autowire = Autowire.BY_TYPE, preConstruction = true)
    public class SessionListener implements HttpSessionListener {

        private static final Logger log;

        @Autowired
        private A a;

        @Override
        public void sessionCreated(HttpSessionEvent se) {
            a.doSomething(); // <- Throws NPE
            log.info("New session was created");
        }

        @Override
        public void sessionDestroyed(HttpSessionEvent se) {
            log.info("A session was closed");
        }
    }

编辑 6:

我简化了示例项目:您现在可以从 CLI 运行它

  1. 下载解压工程:http://www.2shared.com/file/KpS5xeqf/dynatable.html
  2. 运行 mvn clean aspectj:compile
  3. 运行 mvn gwt:run
  4. 您应该在 CLI 中看到“为什么这里的消费者为 NULL?”是 打印。
  5. 应为:cunsumer 不为 NULL!

快结束了:D

编辑 5:GWT 中的示例项目:请在 GWT 开发模式下运行它

http://www.2shared.com/file/eai0PV-5/dynatable.html

你会在 sessionCreated() 获得一个 NPE

运行要求是 maven + gwt 2.5

编辑 4:

示例项目似乎不是一个很有代表性的项目。我应该重新表述问题:

在 Eclipse 中,当我将项目作为 Web 应用程序运行时,我使用 GWT 开发模式。在某种程度上,这不会调用 aspectj 编译器。至少这是我能想到的唯一原因。

问题:如何设置编译时间编织以作为 Web 应用程序运行(GWT 开发模式)。

编辑 3:

我在 Eclipse 4.2.1、M2e 1.4.0、STS 3.1.0、AJDT 2.2.2 中制作了一个小示例项目来演示该问题:http://www.2shared.com/file/WZ1T9l9-/autowired.html

编辑 2:

根据其他类似主题的建议,我采用了标准生成的Roo 项目的插件以避免版本冲突。还没有成功。 (更新了上面的org.codehaus.mojo)

编辑 1:

我不确定这是否正常,但是当我启动 Web 应用程序时,我会看到很长的 spring 正在做什么的日志,但没有提到任何编织/与 Aspectj 相关的任何内容。 ..

我认为问题与 pom.xml 中的这个插件没有被编译为有关当我运行 Web 应用程序时,该插件永远不会被调用:

<plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>aspectj-maven-plugin</artifactId>
                    <version>1.2</version>
                    <!-- NB: do not use 1.3 or 1.3.x due to MASPECTJ-90 and do not use 1.4 
                        due to declare parents issue -->
                    <dependencies>
                        <!-- NB: You must use Maven 2.0.9 or above or these are ignored (see 
                            MNG-2972) -->
                        <dependency>
                            <groupId>org.aspectj</groupId>
                            <artifactId>aspectjrt</artifactId>
                            <version>1.7.0</version>
                        </dependency>
                        <dependency>
                            <groupId>org.aspectj</groupId>
                            <artifactId>aspectjtools</artifactId>
                            <version>1.7.0</version>
                        </dependency>
                    </dependencies>
                    <executions>
                        <execution>
                            <goals>
                                <goal>compile</goal>
                                <goal>test-compile</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <outxml>true</outxml>
                        <aspectLibraries>
                            <aspectLibrary>
                                <groupId>org.springframework</groupId>
                                <artifactId>spring-aspects</artifactId>
                            </aspectLibrary>
                        </aspectLibraries>
                        <source>1.6</source>
                        <target>1.6</target>
                    </configuration>
                </plugin>

原帖:

我一直在搜索 stackoverflow 和许多其他资源,但他们的标准解决方案都没有帮助我找到为什么 @autowired 字段在访问时会变成 Null Pointer Exception (NPE)

@Configurable(autowire = Autowire.BY_TYPE, preConstruction = true)
public class SessionListener implements HttpSessionListener {

    private static final Logger log;

    @Autowired
    private A a;

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        a.doSomething(); // <- Throws NPE
        log.info("New session was created");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        log.info("A session was closed");
    }
}

A类声明如下:

@Service
public class B implements A {
// some implementation
}

我的应用上下文有相关部分:

<context:spring-configured />
<context:annotation-config />
<context:component-scan base-package='some.package' />

所有必要的库都在那里。 我使用 Spring 3.0.2。 由于我的环境,我只能使用编译时编织。 我还使用 Google 插件启动 GWT 开发模式。 我正在使用ADJTSpring Tool Suitem2EclipseGoogle Plugin。我还为 m2e v1.0 安装了 AJDT 配置器。

【问题讨论】:

  • 我已将 ADJT 插件添加到我的项目中,但结果仍然相同。谁能指导我调试这个方法?
  • 您能分享创建您的 A 类的代码吗?
  • 我认为问题不在于那里,因为SessionListener中有几个@autowired,我只是抽象了一个以使代码更简短。无论如何,我在原始帖子中添加了一个示例。并感谢您的回复!
  • 我所看到的一切看起来都不错。如果 B 扩展另一个类或实现任何其他接口(A 除外),则可能会出现一个问题。你能发布更完整的项目代码吗?
  • 是的,听起来像是配置问题。您可以启用跟踪调试,但如何执行取决于您使用的日志记录抽象。

标签: spring aspectj autowired configurable compile-time-weaving


【解决方案1】:

您的 App.main() 方法没有创建 ApplicationContext 开始(JUnit 测试很好,因为它使用 @ContextConfiguration 进行了注释)。为了以编程方式创建它,将以下行添加到您的 main 方法中:

public class App {      
    public static void main( String[] args ) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("foo/application-context.xml");

        new ServiceTest().doSomething();
    }
}

EDIT1:下面的静态解决方案。

缺少 2 个依赖项:

<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-aspects</artifactId>
  <version>${org.springframework.version}</version>
</dependency>
<!-- https://jira.springsource.org/browse/SPR-6819 -->
<dependency>
  <groupId>javax.persistence</groupId>
  <artifactId>persistence-api</artifactId>
  <version>1.0</version>
  <scope>provided</scope>
</dependency>

我还将 ajdtBuildDefFile 插件参数(该文件未包含在存档中)替换为:

<includes>
  <include>**/*.java</include>
</includes>

这样调整pom.xml后,编译测试通过:

mvn clean aspectj:compile test

EDIT1:此解决方案与动态编织有关,但事实并非如此。

要回答您的具体问题,请将其添加到您的 application-context.xml:

<context:load-time-weaver />

还需要 VM 的额外运行时参数:

-javaagent:/full/path/to/spring-instrument-3.0.5.RELEASE.jar

EDIT2:关于 GWT 应用程序

坦率地说,我不确定为什么 aspectj 插件不适用于您的配置。如果您不介意快速解决方法,那么只需使用 WebApplicationContextUtils:

@Override
public void sessionCreated(HttpSessionEvent se) {       
  consumer = WebApplicationContextUtils.getWebApplicationContext(se.getSession().getServletContext()).getBean(IConsumer.class);
  ...
}

【讨论】:

  • A) 是的,我忘了提到要执行的部分是单元测试,而不是主要方法。 B)正如问题所问(我知道它很长)由于环境限制,我只对 CTW 而不是 LTW 感兴趣。
  • 我的错。我已经提交了修改后的解决方案。希望这次能有所帮助。
  • 好的,这帮助我找到了解决方案,谢谢。剩下两件事可以解决我的问题:1)提供的示例现在也可以在这里运行,但实际项目却没有。你介意我做一个小的 GWT 项目吗?我认为这与它是一个实现 HTTPListener 的类有关。 2)使用命令提示符到 aspecjt:compile 然后在 eclipse 中重新导入项目真的很麻烦。您能否详细说明为什么 eclipse 不使用 aspectj:compile,因为它似乎使用 java:compile? (我稍后会在原始帖子中发布编辑)
  • 我认为问题与我必须以 GWT 开发模式(作为 Web 应用程序运行)运行项目有关,因此使用 java 编译器而不是 aspectj。而且我认为即使您事先 mvn aspectj:compile,作为 Web 应用程序运行仍然会重做它。问题更多地转向日食而不是春季问题
  • 'mvn gwt:run' 怎么样?我暂时无法分析您的问题,但我会在今天晚些时候再看看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-02
  • 1970-01-01
  • 2011-05-22
  • 1970-01-01
  • 1970-01-01
  • 2015-07-12
相关资源
最近更新 更多