使用Spring方面和java配置时找不到Bean类型

时间:2013-12-09 08:07:55

标签: spring spring-aop spring-3 wicket-6

我在工作的Spring + Wicket应用程序中添加了一个方面来记录抛出的异常,现在每当我加载Report页面时都会出现以下错误:

ERROR | 2013-12-09 08:42:06,149 | qtp1559334851-16 | DefaultExceptionMapper:123 - Unexpected error occurred
org.apache.wicket.WicketRuntimeException: Can't instantiate page using constructor 'public org.jonblack.ReportPage() throws java.lang.Exception'. An exception has been thrown during construction!
    at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:194)
    at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:67)
    ...
Caused by: java.lang.IllegalStateException: bean of type [org.jonblack.ReportController] not found
    at org.apache.wicket.spring.injection.annot.AnnotProxyFieldValueFactory.getBeanNameOfClass(AnnotProxyFieldValueFactory.java:236)
    at org.apache.wicket.spring.injection.annot.AnnotProxyFieldValueFactory.getBeanName(AnnotProxyFieldValueFactory.java:179)
    ...

我正在为项目使用java配置,因此没有applicationContext.xml。所有配置都通过注释完成,其中大部分都在AppConfig.java

我的应用程序的所有代码如下所示。我遗漏了HTML模板和HomePage,因为它们不是问题的组成部分。

的pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>org.jonblack</groupId>
  <artifactId>sw-p2</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
    <!-- TODO project name  -->
  <name>sw-p2</name>
  <description></description>
  <licenses>
    <license>
      <name>The Apache Software License, Version 2.0</name>
      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
      <distribution>repo</distribution>
    </license>
  </licenses>
  <properties>
    <aspectj.version>1.7.4</aspectj.version>
    <spring.version>3.2.4.RELEASE</spring.version>
    <wicket.version>6.11.0</wicket.version>
    <jetty.version>7.6.3.v20120416</jetty.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
    <!--  WICKET DEPENDENCIES -->
    <dependency>
      <groupId>org.apache.wicket</groupId>
      <artifactId>wicket-core</artifactId>
      <version>${wicket.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.wicket</groupId>
      <artifactId>wicket-extensions</artifactId>
      <version>${wicket.version}</version>
    </dependency>
    <dependency>
      <groupId>org.wicketstuff</groupId>
      <artifactId>wicketstuff-annotation</artifactId>
      <version>${wicket.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.wicket</groupId>
      <artifactId>wicket-spring</artifactId>
      <version>${wicket.version}</version>
    </dependency>
    <!-- Spring dependencies -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!-- aspectj -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>${aspectj.version}</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>${aspectj.version}</version>
    </dependency>
    <!-- LOGGING DEPENDENCIES - LOG4J -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.6.4</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.16</version>
    </dependency>

    <!--  JUNIT DEPENDENCY FOR TESTING -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>

    <!--  JETTY DEPENDENCIES FOR TESTING  -->
    <dependency>
      <groupId>org.eclipse.jetty.aggregate</groupId>
      <artifactId>jetty-all-server</artifactId>
      <version>${jetty.version}</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  <build>
    <resources>
      <resource>
        <filtering>false</filtering>
        <directory>src/main/resources</directory>
      </resource>
      <resource>
        <filtering>false</filtering>
        <directory>src/main/java</directory>
        <includes>
          <include>**</include>
        </includes>
        <excludes>
          <exclude>**/*.java</exclude>
        </excludes>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <filtering>false</filtering>
        <directory>src/test/resources</directory>
      </testResource>
      <testResource>
        <filtering>false</filtering>
        <directory>src/test/java</directory>
        <includes>
          <include>**</include>
        </includes>
        <excludes>
          <exclude>**/*.java</exclude>
        </excludes>
      </testResource>
    </testResources>
    <plugins>
      <plugin>
        <inherited>true</inherited>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.5.1</version>
        <configuration>
          <source>1.7</source>
          <target>1.7</target>
          <encoding>UTF-8</encoding>
          <showWarnings>true</showWarnings>
          <showDeprecation>true</showDeprecation>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>${jetty.version}</version>
        <configuration>
          <connectors>
            <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
              <port>8080</port>
              <maxIdleTime>3600000</maxIdleTime>
            </connector>
            <connector implementation="org.eclipse.jetty.server.ssl.SslSocketConnector">
              <port>8443</port>
              <maxIdleTime>3600000</maxIdleTime>
              <keystore>${project.build.directory}/test-classes/keystore</keystore>
              <password>wicket</password>
              <keyPassword>wicket</keyPassword>
            </connector>
          </connectors>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-eclipse-plugin</artifactId>
        <version>2.9</version>
        <configuration>
          <downloadSources>true</downloadSources>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

AppConfig.java

package org.jonblack;

import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.Executor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ComponentScan;
//import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@ComponentScan("org.jonblack")
@EnableAsync
@EnableAspectJAutoProxy()
public class AppConfig {
  private static final Logger log = LoggerFactory.getLogger(AppConfig.class);

  @Bean
  public ReportController reportController() {
    log.info("Getting ReportController");
    return new ReportController();
  }

  @Bean
  public ThreadPoolTaskExecutor taskExecutor() {
    ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
    pool.setCorePoolSize(5);
    pool.setMaxPoolSize(10);
    pool.setWaitForTasksToCompleteOnShutdown(true);
    return pool;
  }

  @Bean
  public ExceptionLoggingAspect exceptionLoggingAspect() {
    return new ExceptionLoggingAspect();
  }

  @Bean
  public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator() {
    AnnotationAwareAspectJAutoProxyCreator aop = new AnnotationAwareAspectJAutoProxyCreator();
    return aop;
  }
}

ExceptionLoggingAspect.java

package org.jonblack;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;

import org.springframework.stereotype.Component;


@Aspect
@Component
public class ExceptionLoggingAspect {
  private static final Logger LOG = LoggerFactory.getLogger(ExceptionLoggingAspect.class);

  @AfterThrowing(pointcut="execution(* org.jonblack.ReportController.getReportData(..))", throwing="ex")
  public void afterThrowing(Throwable ex) {
    LOG.error(ex.getMessage());
  }

}

ReportController.java

package org.jonblack;


import java.util.concurrent.Callable;
import java.util.concurrent.Future;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Controller;

@Controller
public class ReportController {
  private static final Logger log = LoggerFactory.getLogger(ReportController.class);

  @Autowired
  private ThreadPoolTaskExecutor taskExecutor;

  @Async
  public Future<String> getReportData() throws Exception {
    log.info("Entered into getReportData()");

    try {
      log.info("Throwing an exception");
      throw new Exception("Something went wrong");
    } catch(Exception ex) {
      log.error("In catch block: {}", ex.getMessage());
    }

    final Future<String> result = taskExecutor.submit(new Callable<String>() {
      @Override
      public String call() throws Exception {
        return "not a fancy result";
      }
    });

    log.info("Returning from getReportData()");
    return result;
  }
}

ReportPage.java

package org.jonblack;

import java.util.concurrent.Future;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.wicketstuff.annotation.mount.MountPath;


@MountPath("report")
public class ReportPage extends WebPage {
  private static final Logger log = LoggerFactory.getLogger(ReportPage.class);

  @SpringBean
  ReportController reportController;

  public ReportPage() throws Exception {
    log.info("Starting ReportPage");

    reportController.getReportData();
  }
}

WicketApplication.java

package org.jonblack;

import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.spring.injection.annot.SpringComponentInjector;
import org.wicketstuff.annotation.scan.AnnotatedMountScanner;


public class WicketApplication extends WebApplication
{
  @Override
  public Class<? extends WebPage> getHomePage()
  {
    return HomePage.class;
  }

  @Override
  public void init()
  {
    super.init();

    // Spring
    getComponentInstantiationListeners().add(
        new SpringComponentInjector(this));

    // Annotation-driven page mounting
    new AnnotatedMountScanner().scanPackage("org.jonblack").mount(this);
  }
}

的web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  version="2.5">

  <display-name>sw-p2</display-name>

  <!-- Configuration loading -->
  <context-param>
    <param-name>contextClass</param-name>
    <param-value>
      org.springframework.web.context.support.AnnotationConfigWebApplicationContext
    </param-value>
  </context-param>

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>org.jonblack.AppConfig</param-value>
  </context-param>

  <!-- Spring -->
  <listener>
    <listener-class>
      org.springframework.web.context.ContextLoaderListener
    </listener-class>
  </listener>

  <!-- Wicket -->
  <filter>
    <filter-name>wicket.sw-p2</filter-name>
    <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
    <init-param>
      <param-name>applicationClassName</param-name>
      <param-value>org.jonblack.WicketApplication</param-value>
    </init-param>
  </filter>

  <filter-mapping>
    <filter-name>wicket.sw-p2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

我已经关注了Spring reference for Aspects但是当涉及到java配置时,它的实力非常薄(而且我觉得这个参考很难遵循)。

我还完成了强制性的DuckDuckGo搜索,并且只找到了对XML配置的引用。

在stackoverflow本身,我发现this post解释了同样的问题,但是该实例中的原因是注释不正确并且命名错误的applicationContext.xml文件:这些都没有帮助解决我的情况。我尝试使用@Autowired代替@SpringBean,并获得相同的NullPointerException。鉴于链接的帖子在没有这种变化的情况下解决了它,我认为这不是正确的路径。

1 个答案:

答案 0 :(得分:1)

问题在于您的配置。

@Bean
public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator() {
    AnnotationAwareAspectJAutoProxyCreator aop = new AnnotationAwareAspectJAutoProxyCreator();
    return aop;
 }

这个bean导致创建代理的代理。 @EnableAspectJAutoProxy注释已注册AutoProxyCreator,并且由于存在多个不同的实例,这将导致代理重复。

除此之外,您方面的附加声明可能会导致实例化2个方面。

@Bean
public ExceptionLoggingAspect exceptionLoggingAspect() {
  return new ExceptionLoggingAspect();
}

您的@Aspect也是@Component,因此@ComponentScan功能会检测到这一点。

基本上删除这两个bean应该可以解决您的问题。

public Future<String> getReportData() throws Exception {
    log.info("Entered into getReportData()");

    try {
      log.info("Throwing an exception");
      throw new Exception("Something went wrong");
    } catch(Exception ex) { // This catch blocks swallows the exception
      log.error("In catch block: {}", ex.getMessage()); 
    }
}

在配置问题旁边,您的代码也存在问题。基本上你的方面是没用的。你的代码中有一个try / catch块吞下Exception。这种吞咽导致您的方面永远不会看到异常而永远不会触发的情况。从您的角度来看,异常从未发生过。

要么不抓住,只要让Exception冒泡到堆栈或重新抛出Exception