使用Spring创建bean时不满意的依赖异常

时间:2017-10-08 12:03:51

标签: java spring spring-mvc

我正在尝试将JPA用于我的spring应用程序。我已经集成了JPATransactionManager&将LocalEntityManagerFactoryBean转换为AppConfig类。现在,当我尝试调用DaoImpl中的方法之一时,AppConfig无法对类进行自动装配。这是我的代码

Test Class

public class Test {
public static void main(String[] args) {
      AnnotationConfigApplicationContext context = 
            new AnnotationConfigApplicationContext(AppConfig.class);

      BbDao personService = context.getBean(BbDao.class);
      personService.getDealByDealId("0194541605021NJMAPFU");
      context.close();
   }
}

的AppConfig

@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan(basePackages = "net.bb.spring")
public class AppConfig{

 @Bean
   public LocalEntityManagerFactoryBean getEntityManagerFactoryBean() {
      LocalEntityManagerFactoryBean factoryBean = new LocalEntityManagerFactoryBean();
      factoryBean.setPersistenceUnitName("MyPersistence");
      return factoryBean;
   }

   @Bean
   public JpaTransactionManager geJpaTransactionManager() {
      JpaTransactionManager transactionManager = new JpaTransactionManager();
      transactionManager.setEntityManagerFactory(getEntityManagerFactoryBean().getObject());
      return transactionManager;
   }

}

ConfirmPurchaseController

@RestController
public class ConfirmPurchaseController {

private Logger logger = Logger.getLogger(ConfirmPurchaseController.class);

@Autowired
private MyService myService;

@GetMapping("/purchase")
public ResultDto confirmpurchase(HttpServletResponse response) throws ClassNotFoundException, IOException {
    // Business Logic    
}
}

为MyService

@Component
public interface MyService {
    // Methods defined
}

MyServiceImpl

@Service
public class MyServiceImpl implements MyService, ServletContextAware {

private ServletContext servletContext;

public void setServletContext(ServletContext servletContext) {
    this.servletContext = servletContext;
}

public ServletContext getServletContext() {
    return servletContext;
}


// Added the implemented methods of the MyService Interface
} 

它抛出的例外是

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myServiceImpl': Unsatisfied dependency expressed through field 'servletContext'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.servlet.ServletContext' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

,错误日志为

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'confirmPurchaseController': Unsatisfied dependency expressed through field 'myService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myServiceImpl': Unsatisfied dependency expressed through field 'servletContext'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.servlet.ServletContext' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
at net.bb.spring.controller.Test.main(Test.java:14)

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myServiceImpl': Unsatisfied dependency expressed through field 'servletContext'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.servlet.ServletContext' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
... 14 more

 Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.servlet.ServletContext' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
... 27 more

任何想法对我都非常有用。

P.S:我使用配置作为注释,没有XML

3 个答案:

答案 0 :(得分:0)

这不是答案,但我还不能添加评论。

您是否尝试通过setter方法自动装配ServletContext? - 从属性中删除@Autowired - 删除你的一个setter上下文(不必要的重复) - 将setter标记为@Autowired

此外,从MyService中删除@Component注释,如果在其实现中使用@Service注释,则没有必要。

答案 1 :(得分:0)

根据Apache Tomcat文档,ServletContext

  

定义servlet用于与其通信的一组方法   servlet容器。

     

每个Java虚拟机每个“Web应用程序”有一个上下文。   (“Web应用程序”是安装的servlet和内容的集合   在服务器的URL命名空间的特定子集下,例如/ catalog   并可能通过.war文件安装。)

这意味着ServletContext仅在像Apache Tomcat这样的Servlet容器中有效。但正如我所看到的,您正试图通过在main方法中创建bean来运行普通的Java应用程序,这会使ServletContext的存在无效。

所以你需要做的是:

步骤1:构建AppConfig并覆盖所需的方法。

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"net.bb.spring"})
public class AppConfig extends WebMvcConfigurerAdapter {

        @Override
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
        }

        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/");
        }
        //....
    }

第2步:创建WebInitializer以初始化Dispatcher Servlet

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] {AppConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }

}

步骤3:创建服务层以自动装配ServletContext

@Service
public class MyServiceImpl implements MyService {
    private ServletContext servletContext;

    @Autowire
    public MyServiceImpl(ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    public ServletContext getServletContext() {
        return servletContext;
    }

    //...
}

第4步:将应用程序构建到WAR文件

步骤5:将WAR文件部署到Tomcat的webapp文件夹(如果您使用的是Tomcat)

第6步:启动Tomcat

答案 2 :(得分:0)

这是您需要更改的内容:

1)您不需要使用@Component注释接口,仅在实现类上需要注释

我的服务

public interface MyService {
    // Methods defined
}

2)使用构造函数注入获得ServeletContext的实例。

@Service
public class MyServiceImpl implements MyService, ServletContextAware {
    private ServletContext servletContext;

    @Autowire
    public MyServiceImpl(ServletContext servletContext) {
        this.servletContext = servletContext;
    }



    //TODO: other methods goes here...
}

请注意,ServletContext不是Spring bean,因此除非实现ServletContextAware,否则无法注入它。保持实现类implements ServletContextAware