编译时间编织空指针异常

时间:2013-02-23 23:44:56

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

编辑7:

问题似乎是如何让@Configurable使用HttpSessionListener,建议采用解决方法,但我不想直接与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中看到“为什么消费者为空?”是 打印。
  5. 预计会改为:cunsumer不是NULL!
  6. 结束了: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:

    我不确定这是否正常,但是当我启动网络应用程序时,我会详细记录春天正在做什么,但没有提及任何编织/与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。 由于我的环境,我只能使用编译时编织。 我也在使用谷歌插件启动GWT开发模式。 我正在使用ADJTSpring Tool Suitem2EclipseGoogle Plugin。我还为m2e v1.0安装了AJDT配置器。

1 个答案:

答案 0 :(得分: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 app相关

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

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