ApplicationContextInitializer

ApplicationContextInitializer

本文介绍了NoSuchBeanDefinitionException:没有为依赖项找到类型[Repository]的限定bean:预期至少有1个bean有资格作为autowire的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现类似的问题解释了许多门户网站。但我想这是独特的情况。我在spring mvc app中收到错误。

I found similar issues explained many web portals. But I guess this is unique situation. I am getting an error in spring mvc app.

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testController' defined in file [C:\Program Files (x86)\sts-bundle\pivotal-tc-server-developer-3.1.2.RELEASE\base-instance\wtpwebapps\ExpT1\WEB-INF\classes\com\expt\controller\TestController.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.expt.repositories.CategoryRepository]: No qualifying bean of type [com.expt.repositories.CategoryRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.expt.repositories.CategoryRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
    org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
    org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185)

.....

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.expt.repositories.CategoryRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
    org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373)

代码如下。我认为已经复制了足够多的代码。请帮助我了解缺少的内容以及如何解决此问题。任何帮助都会很棒...... !!
代码:
Appinitializer:

The code is given below. I think enough code has been copied. Please help me to understand what is missing and how I can fix this issue. Any help would be great...!!Code:Appinitializer:

package com.expt.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;


public class AppInitialzer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        // TODO Auto-generated method stub
        return new Class[]{SpringAppContInit.class, SQLDevDataSource.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        // TODO Auto-generated method stub
        return new Class[]{WebMvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        // TODO Auto-generated method stub
        return new String[]{"/"};
    }

}

SQLDEVConfig:

SQLDEVConfig:

package com.expt.config;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@Configuration
@Profile("SQLDev")
@EnableJpaRepositories(basePackages={"com.expt.repositories"})
public class SQLDevDataSource extends AbstractJpaConfig {

    @Override
    public DataSource getDataSource() {
        // TODO Auto-generated method stub
        return createBasicDataSource("jdbc:jtds:sqlserver://LOCAL:1433/MYDB;", "net.sourceforge.jtds.jdbc.Driver", "UNMA", "PWD123");
    }
    public BasicDataSource createBasicDataSource(String jdbcUrl, String driverClass, String userName, String password) {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setUrl(jdbcUrl);
        dataSource.setDriverClassName(driverClass);
        dataSource.setUsername(userName);
        dataSource.setPassword(password);
        return dataSource;
    }

}

SpringAPpContInit:

SpringAPpContInit:

package com.expt.config;

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

public class SpringAppContInit implements ApplicationContextInitializer<AnnotationConfigWebApplicationContext> {

    @Override
    public void initialize(AnnotationConfigWebApplicationContext applicationContext) {
        // TODO Auto-generated method stub
        ConfigurableEnvironment configEnv = applicationContext.getEnvironment();
        configEnv.addActiveProfile("SQLDev");
    }

}

AbstrackJpaConfig:

AbstrackJpaConfig:

   package com.expt.config;

import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceProvider;
import javax.sql.DataSource;

import org.hibernate.dialect.SQLServer2008Dialect;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.orm.jpa.JpaDialect;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import com.expt.domain.Category;

public abstract class AbstractJpaConfig {

    public abstract DataSource getDataSource();

    @Bean(name="entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource){
        Map<String, String> properties = new HashMap<String, String>();
        properties.put(org.hibernate.cfg.Environment.HBM2DDL_AUTO, "validate");
        properties.put(org.hibernate.cfg.Environment.DIALECT, SQLServer2008Dialect.class.getName());
        properties.put(org.hibernate.cfg.Environment.SHOW_SQL, "true");

        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource);
        //em.setPackagesToScan(Expense.class.getPackage().getName());
        em.setPackagesToScan(Category.class.getPackage().getName());
        //em.setPersistenceProvider(new HibernatePersistenceProvider());
        em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        em.setJpaPropertyMap(properties);       
        return em;
    }

    @Bean(name = "transactionManager")
    public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

控制器:

package com.expt.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.expt.domain.Category;
import com.expt.repositories.CategoryRepository;

@RestController
@RequestMapping("/test")
public class TestController {

    CategoryRepository catRepo;

    @Autowired
    public TestController(CategoryRepository catRepo) {
        this.catRepo = catRepo;
    }

    /*private CategoryService catSvc;

    @Autowired
    public TestController(CategoryService catSvc) {
        this.catSvc = catSvc;
    }*/

    @RequestMapping("/simple")
    public String test(){
        return "testing";
    }

    @RequestMapping("/json")
    public Iterable<Category> testJ(){
        return catRepo.findAll();
    }
}

CategoryRepository:

CategoryRepository:

package com.expt.repositories;

import java.math.BigDecimal;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import com.expt.domain.Category;

@Repository
public interface CategoryRepository extends JpaRepository<Category, BigDecimal> {

}

=========== ==============================================

=========================================================

(由于添加了很多评论,想要添加这些细节)

(As there are lot of comments added to this, thought to add these details as well)

我指的是。其中使用公共类AppInitializer为appinitializer实现了WebApplicationInitializer

完全代码在这里,我在我的使用中旧项目。这会手动注册配置类,但它正在工作。但是当我们从 AbstractAnnotationConfigDispatcherServletInitializer 扩展时它不需要。

Full Code is here, what I was using in my old project. This does manually registering the configuration classes and it was working. But it does not require when we extend from AbstractAnnotationConfigDispatcherServletInitializer.

   public class AppInitializer implements WebApplicationInitializer{

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        // TODO Auto-generated method stub
        configureAppContextInitializers(servletContext, SpringAppContInit.class.getName());

        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(RepositoryConfig.class);
        servletContext.addListener(new ContextLoaderListener(rootContext));

        AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
        webContext.register(WebMvcConfig.class);

        DispatcherServlet dispatcherServlet = new DispatcherServlet(webContext);
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", dispatcherServlet);
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }

    private void configureAppContextInitializers(ServletContext container, String... initClassNames) {
        String initializerClasses = container.getInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM);

        String delimitedClassNames = StringUtils.arrayToDelimitedString(initClassNames, " ");

        if (StringUtils.hasText(initializerClasses)) {
            initializerClasses += " " + delimitedClassNames;
        }
        else {
            initializerClasses = delimitedClassNames;
        }

        container.setInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM, initializerClasses);
    }
}

如果是 AbstractAnnotationConfigDispatcherServletInitializer ,方法 getRootConfigClasses getServletConfigClasses 隐式注册。现在我正在寻找原因为什么我上面的代码不起作用。我有一些解决方法,我可以通过恢复到XML或 WebApplicationInitializer 来使其工作。我正在寻找一个解决方案,并尽可能使用更新的代码而不是API文档。我需要一个教程。 API文档无法帮助我解决问题。

In case of AbstractAnnotationConfigDispatcherServletInitializer, the methods getRootConfigClasses and getServletConfigClasses do the registering implicitly.Now I am looking for the reason why my above code is not working. I have workaround like I can make it working by reverting back to XMLs or WebApplicationInitializer. I am looking for a solution and reason if possible with updated code rather than API document. I need a tutorial. API document wont help me to resolve the issue.

推荐答案

您自己实现的 WebApplicationInitializer 和扩展 AbstractAnnotationConfigDispatcherServletInitializer 的实现是不同的。它们表现不同,这是因为您没有注册自定义。如何注册 ApplicationContextInitializer 在(注意设置 ApplicationContextInitializer s集合的2种方法。)。

Your own implementation of the WebApplicationInitializer and the implementation extending AbstractAnnotationConfigDispatcherServletInitializer are different. They behave different and that is because you aren't registering your custom ApplicationContextInitializer. How to register the ApplicationContextInitializer is explained in the javadoc (notice the 2 methods to set a collection of ApplicationContextInitializers.).

public class AppInitialzer extends AbstractAnnotationConfigDispatcherServletInitializer {

    ...    

    protected ApplicationContextInitializer<?>[] getRootApplicationContextInitializers() {
        return new ApplicationContextInitializer[] { new SpringAppContInit() } ;
    }
}

然而 ApplicationContextInitializer 并没有真正添加任何通过简单设置环境或系统属性而无法完成的操作。

However that ApplicationContextInitializer doesn't really add anything that cannot already be done by simply setting an environment or system property.

spring.profiles.active=SQLDev

当你这样做时,你不需要那个init。

When you do that you don't need that init.

我也坚信你的 @EnableJpaRepositories 是在错误的类上,你想要启用那些不应该取决于你的个人资料。

I also strongly believe that your @EnableJpaRepositories is on the wrong class, the fact that you want to enable those shouldn't depend on your profile.

这篇关于NoSuchBeanDefinitionException:没有为依赖项找到类型[Repository]的限定bean:预期至少有1个bean有资格作为autowire的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-16 13:04