2015-08-27 6 views
1

Я просто хочу начать с того, что я новичок в Spring, JPA и в спящем режиме. Поэтому я стараюсь изо всех сил. Кроме того, я использую конфигурацию на основе Java, поэтому здесь не используется xml.Почему я получаю исключение NoSuchBeanDefinitionException, когда я уже определил компонент?

Итак, я пытаюсь запустить интеграционный тест на моем классе PersonDAOJpa. Пока я запускаю интеграционный тест, я получаю сообщение об ошибке для NoSuchBeanDefinitionException для bean-компонента jpaDao. Я уже определил компонент в моем классе DatabaseConfig. Так почему я получаю эту ошибку, хотя я ее определил?

Вот код и ошибки трассировки, которые должны иметь отношение к этому вопросу:

Трассировка Ошибка:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'jpaDao' is defined 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1168) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:281) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) 
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:962) 
    at com.orgchart.PersonServiceJPAIntegrationTest.<init>(PersonServiceJPAIntegrationTest.java:34) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) 
    at java.lang.reflect.Constructor.newInstance(Unknown Source) 
    at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:217) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:199) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:259) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:261) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:219) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 

DatabaseConfig:

@Configuration 
@PropertySource("classpath:application.properties") 
@EnableTransactionManagement 
public class DatabaseConfig{ 



    @Bean(name="jpaDao") 
    public PersonDAOJpa jpadao(){ 

     return new PersonDAOJpa(); 

    } 

    @Bean(name="jdbcDao") 
    public PersonDAOJdbc dao(){ 

     return new PersonDAOJdbc(); 

    } 


    @Bean 
    public JdbcTemplate jdbc(DataSource ds){ 

     JdbcTemplate jdbc= new JdbcTemplate(dataSource()); 

     return jdbc; 
    } 


    @Bean 
    public PersonService ps(){ 

     PersonService ps= new PersonServiceImpl(); 

     return ps; 
    } 


    @Bean(name="ds") 
    public DataSource dataSource() { 

     DriverManagerDataSource ds = new DriverManagerDataSource(); 
     ds.setDriverClassName("com.mysql.jdbc.Driver"); 
     ds.setUrl("jdbc:mysql://localhost:3306/------"); 
     ds.setUsername(" "); 
     ds.setPassword(" "); 

     return ds; 

    } 


    @Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() { 

     LocalContainerEntityManagerFactoryBean em = 
      new LocalContainerEntityManagerFactoryBean(); 
     em.setDataSource(dataSource()); 
     em.setPackagesToScan(new String[] {"com.orgchart"}); 
     JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
     em.setJpaVendorAdapter(vendorAdapter); 
     em.setJpaProperties(additionalProperties()); 
     return em; 
    } 


    @Bean 
    public PlatformTransactionManager transactionManager() { 

     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(entityManagerFactoryBean() 
      .getObject()); 
     return transactionManager; 
    } 


    @Bean 
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { 

     return new PersistenceExceptionTranslationPostProcessor(); 
    } 


    Properties additionalProperties() { 

     return new Properties() { 

      private static final long serialVersionUID = 1L; 

      { // Hibernate Specific: 
       setProperty("hibernate.hbm2ddl.auto", "update"); 
       setProperty("hibernate.dialect", 
        "org.hibernate.dialect.MySQL5Dialect"); 
      } 
     }; 

    } 



} 

IntegrationTest:

@ContextConfiguration(classes = {IntegrationTestConfig.class}) 
@RunWith(SpringJUnit4ClassRunner.class) 
public class PersonServiceJPAIntegrationTest { 



    ApplicationContext context= new AnnotationConfigApplicationContext(DatabaseConfig.class); 

    PersonDAO personDao = context.getBean("jpaDao", PersonDAO.class); 

    PersonServiceImpl ps = new PersonServiceImpl(personDao); 


    @Before 
    public void setUp() throws Exception { 


    } 



    @After 
    public void tearDown() throws Exception { 

    } 

...... 


} 

PersonDAOJpa:

@Component("jpaDao") 
public class PersonDAOJpa implements PersonDAO{ 



     @PersistenceContext 
     private EntityManager em; 



     public PersonDAOJpa(){ 

     } 


     public EntityManager getEm() { 

      return em; 
     } 


     public void setEm(EntityManager em) { 

      this.em = em; 
     } 

    ..... 

} 

** UPDATE:

IntegrationTestConfig:

import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 



@Configuration 
@ComponentScan 
public class IntegrationTestConfig { 


} 

Кроме того, существует служба слой в моем приложении, я просто не добавить его ниже, потому что я не» t хочу добавить нерелевантную информацию. Но если вам это нужно или вам нужно больше кода или информации, я добавлю его.

+0

вставьте источник IntegrationTestConfig.class –

+0

В моем IntegrationTestConfig нет действительного кода. Я просто использовал аннотации и работает. – AGI

+0

Может быть, потому, что вы используете jpaDao для имени бобов и имени компонента? можете ли вы изменить название компонента на что-то еще и попробовать? –

ответ

0

Проблема с вашей аннотацией @ComponentScan. Поскольку вы не определили базовые пакеты (пакеты для сканирования) по умолчанию, он использует текущий пакет вашего теста в качестве целевого пакета.

Изменить это:

@ComponentScan(basePackages = {"package.of.your.jpa.classes"}) 

, чтобы заставить его работать.

0

Без вашего класса IntegrationTestConfig это немного догадка, но я собираюсь угадать, что ваш тест на самом деле не тянет ваш класс конфигурации базы данных.

В вашем IntegrationTest классе, попробуйте изменить

@ContextConfiguration(classes = {IntegrationTestConfig.class}) 

в

@ContextConfiguration(classes = {IntegrationTestConfig.class, DatabaseConfig.class}) 

Кстати, вы делаете избыточную конфигурацию, которая может вызвать проблемы. Например, вы создаете экземпляр PersonDAOJpa с использованием аннотации @Bean в классе конфигурации, но вы также отметили PersonDAOJpa для компонентного сканирования, аннотируя сам класс @Component. Сделайте то или другое, а не то и другое. Мое личное предпочтение заключается в использовании классов конфигурации и аннотаций @Bean, где для создания компонента добавлены дополнительные шаги. Когда компонент, который я хочу, представляет собой простой экземпляр, созданный с помощью конструктора по умолчанию, я отмечаю его для компонентного сканирования, например, с помощью @Component .. тогда Spring создает экземпляр для меня.

Наконец, в тех случаях, когда вы используете класс конфигурации и аннотацию @Bean, экземпляр bean будет использовать имя метода. Так что, если бы я создать PersonDAOJpa боб, как это (вместо компонента-сканирования):

@Bean 
public PersonDAOJpa myPersonDao() { 
    return new PersonDAOJpa(); 
} 

тогда фасоль будет иметь название «myPersonDao» в контексте Spring приложения. Обратите внимание, что обычно вам не нужно беспокоиться о имени в любом случае, потому что Spring автоматически прокладывает по типу, а не по имени, если вы не говорите ему об этом иначе. Имена имеют значение только тогда, когда вам нужно иметь более одного компонента одного и того же класса, а затем вам нужно будет квалифицировать их по имени (я не рекомендую этот шаблон, но иногда это должно произойти).

0

Изменить определение Bean вернуть интерфейс PersonDAO

@Bean(name="jpaDao") 
public PersonDAO jpadao(){ 

    return new PersonDAOJpa(); 

} 

Таким образом, эта линия

PersonDAO personDao = context.getBean("jpaDao", PersonDAO.class); 

будет найти правильный тип компонента.

Смежные вопросы