2017-01-05 6 views
1

Это может показаться явной ошибкой, но я не могу ее найти. Ниже мой код и конфигурации:@Autowired не работает для JdbcTemplate, когда DAO имеет @Repository

Класс Application

@SpringBootApplication 
public class Application { 
    public static void main(final String[] args) { 
     SpringApplication.run(Application.class, args); 
    } 
} 

SQL Config класса

@Configuration 
public class PostgreSQLConfig { 
    @Bean 
    public DataSource getDBDataSource() { 
     final DriverManagerDataSource driverManagerDataSource 
       = new DriverManagerDataSource(
         "jdbc:postgresql://localhost:5432/applicationdb", 
         "username", 
         "password" 
       ); 

     driverManagerDataSource.setDriverClassName("org.postgresql.Driver"); 
     return driverManagerDataSource; 
    } 


    @Bean 
    public JdbcTemplate getJdbcTemplate(final DataSource dataSource) { 
     return new JdbcTemplate(dataSource); 
    } 
} 

@Repository DAO КЛАСС

@Repository 
public class CustomDAO { 

    @Autowired 
    private JdbcTemplate jdbcTemplate; 
    . 
    . 

@Component DAO класса

@Component 
public class AnotherDAO { 

    @Autowired 
    private JdbcTemplate jdbcTemplate; 
    . 
    . 

Объект JdbcTemplate заселяется за @Component аннотированный класс. Но объект имеет значение null для @Repository аннотированного класса. Я начал весеннюю загрузку с регистрацией, установленной в DEBUG, и не смог найти никакой ошибки при создании JdbcTemplate bean. Из журналов я могу сделать вывод, что метод вызывается, и компонент создается. JdbcTemplate также имеет ссылку на DataSource.

Если аннотация @Repository изменена на @Component, код работает нормально.

  1. При использовании пружины JDBC, мы можем аннотировать класс DAO с @Repository?
  2. Почему инъекция зависимостей работает с @Component, но не для @Repository?

Согласно предложению М. Дейна, я внесла следующие изменения.

  • Удален PostgreSQLConfig класса
  • Добавлен application.properties файлового

application.properties

spring.datasource.url=jdbc:postgresql://localhost:5432/applicationdb 
spring.datasource.user=username 
spring.datasource.password=password 
spring.datasource.driver-class-name=org.postgresql.Driver 

Свойства загружаются яровым приложением. Ниже приведены сообщения журнала:

2017-01-06 15:03:02 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Found key 'spring.datasource.driver-class-name' in [applicationConfigurationProperties] with type [String] 
2017-01-06 15:03:02 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Found key 'spring.datasource.password' in [applicationConfigurationProperties] with type [String] 
2017-01-06 15:03:02 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Found key 'spring.datasource.user' in [applicationConfigurationProperties] with type [String] 
2017-01-06 15:03:02 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Found key 'spring.datasource.url' in [applicationConfigurationProperties] with type [String] 

Получалось исключение. Ниже приведены детали:

2017-01-06 15:03:05 [main] DEBUG o.s.b.d.LoggingFailureAnalysisReporter - Application failed to start due to an exception 
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.jdbc.core.JdbcTemplate' 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:1474) 

классы DAO отмечены @Repository аннотацию.

build.gradle

buildscript { 
    repositories { 
     mavenCentral() 
    } 

    dependencies { 
     classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.4.3.RELEASE' 
    } 
} 


apply plugin: 'java' 
apply plugin: 'war' 
apply plugin: 'idea' 
apply plugin: 'application' 
apply plugin: 'org.springframework.boot' 


def applicationVersion = '0.0.1-SNAPSHOT' 

def dependencyVersions = [ 
    slf4j: '1.7.22', 
    logback: '1.1.8', 
    postgresql: '9.4.1212', 
    junit: '4.12' 
] 


group = 'com.appl' 
version = applicationVersion 
mainClassName = 'com.appl.Application' 


war { 
    baseName = 'my-custom-appl' 
    version = applicationVersion 
} 

war.dependsOn test 


repositories { 
    mavenCentral() 
} 


sourceCompatibility = 1.8 
targetCompatibility = 1.8 


configurations.all { 
    exclude group: 'commons-logging', module: 'commons-logging' 
} 


dependencies { 
    compile 'org.springframework.boot:spring-boot-starter-web' 
    compile 'org.springframework.boot:spring-boot-starter-jdbc' 
    compile 'org.springframework:spring-jdbc' 
    compile "org.slf4j:jcl-over-slf4j:${dependencyVersions.slf4j}" 
    compile "org.postgresql:postgresql:${dependencyVersions.postgresql}" 
    compile "ch.qos.logback:logback-classic:${dependencyVersions.logback}" 
    testCompile "junit:junit:${dependencyVersions.junit}" 
    testCompile 'org.springframework.boot:spring-boot-starter-test' 
} 
+0

Просто для подтверждения, вы проверили свое заявление об импорте! –

+0

Все аннотации импортированы правильно. Для JdbcTemplate я дважды проверял себя. –

+0

Я забыл упомянуть в вопросе, я использую Spring 4.3.5.RELEASE. Я развивался для продукта POC. –

ответ

0

Я нашел (что происходит часть) решения проблемы. Методы в классе DAO были отмечены final, а @Repository не работает с методом final. Из журналов я могу сделать вывод, что @Repository пытается создать прокси для класса DAO, который терпит неудачу.

Когда @Repository заменен на @Component, код работает нормально. Снова из журналов я вижу, что @Component не создает прокси и final статус метода игнорируется.

Ниже приведены отладочные журналы Spring:

Когда метод является окончательным и DAO класса отмечен как @Repository

2017-01-08 09:19:03 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Autowiring by type from bean name 'customDAO' via constructor to bean named 'getJdbcTemplate' 
2017-01-08 09:19:03 [main] DEBUG c.j.l.d.CustomDAO - Received JdbcTemplate: [email protected] 
2017-01-08 09:19:03 [main] INFO c.j.l.d.CustomDAO - Constructor Called 
2017-01-08 09:19:03 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'customDAO' to allow for resolving potential circular references 
2017-01-08 09:19:03 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor' 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Creating CGLIB proxy: target source is SingletonTargetSource for target object [[email protected]] 
2017-01-08 09:19:03 [main] INFO o.s.aop.framework.CglibAopProxy - Unable to proxy method [public final int com.j.l.data.CustomDAO.persistEvent(java.util.List)] because it is final: All calls to this method via a proxy will NOT be routed to the target instance. 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Found 'equals' method: public boolean java.lang.Object.equals(java.lang.Object) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: public java.lang.String java.lang.Object.toString() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Found 'hashCode' method: public native int java.lang.Object.hashCode() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract int org.springframework.aop.framework.Advised.indexOf(org.springframework.aop.Advisor) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract int org.springframework.aop.framework.Advised.indexOf(org.aopalliance.aop.Advice) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.isFrozen() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.setTargetSource(org.springframework.aop.TargetSource) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.addAdvisor(org.springframework.aop.Advisor) throws org.springframework.aop.framework.AopConfigException 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.addAdvisor(int,org.springframework.aop.Advisor) throws org.springframework.aop.framework.AopConfigException 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.setExposeProxy(boolean) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.isExposeProxy() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.isProxyTargetClass() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract org.springframework.aop.TargetSource org.springframework.aop.framework.Advised.getTargetSource() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.setPreFiltered(boolean) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.addAdvice(int,org.aopalliance.aop.Advice) throws org.springframework.aop.framework.AopConfigException 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.addAdvice(org.aopalliance.aop.Advice) throws org.springframework.aop.framework.AopConfigException 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.isPreFiltered() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract java.lang.Class[] org.springframework.aop.framework.Advised.getProxiedInterfaces() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.isInterfaceProxied(java.lang.Class) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract org.springframework.aop.Advisor[] org.springframework.aop.framework.Advised.getAdvisors() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.removeAdvisor(int) throws org.springframework.aop.framework.AopConfigException 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.removeAdvisor(org.springframework.aop.Advisor) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.replaceAdvisor(org.springframework.aop.Advisor,org.springframework.aop.Advisor) throws org.springframework.aop.framework.AopConfigException 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.removeAdvice(org.aopalliance.aop.Advice) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract java.lang.String org.springframework.aop.framework.Advised.toProxyConfigString() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract java.lang.Class org.springframework.aop.TargetClassAware.getTargetClass() 
2017-01-08 09:19:03 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'customDAO' 

Когда метод не является окончательным и класс DAO отмечен как @Repository

2017-01-08 09:19:03 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'getJdbcTemplate' 
2017-01-08 09:19:03 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Autowiring by type from bean name 'anotherDAO' via constructor to bean named 'getJdbcTemplate' 
2017-01-08 09:19:03 [main] DEBUG c.j.l.data.AnotherDAO - Received JdbcTemplate: [email protected] 
2017-01-08 09:19:03 [main] INFO c.j.l.data.AnotherDAO - Constructor Called 
2017-01-08 09:19:03 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'anotherDAO' to allow for resolving potential circular references 
2017-01-08 09:19:03 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor' 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Creating CGLIB proxy: target source is SingletonTargetSource for target object [[email protected]] 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: public void com.j.l.data.AnotherDAO.persistEvent(com.j.l.model.EmergencyUserResponse) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Found 'equals' method: public boolean java.lang.Object.equals(java.lang.Object) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: public java.lang.String java.lang.Object.toString() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Found 'hashCode' method: public native int java.lang.Object.hashCode() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract int org.springframework.aop.framework.Advised.indexOf(org.springframework.aop.Advisor) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract int org.springframework.aop.framework.Advised.indexOf(org.aopalliance.aop.Advice) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.isFrozen() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.setTargetSource(org.springframework.aop.TargetSource) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.addAdvisor(org.springframework.aop.Advisor) throws org.springframework.aop.framework.AopConfigException 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.addAdvisor(int,org.springframework.aop.Advisor) throws org.springframework.aop.framework.AopConfigException 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.setExposeProxy(boolean) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.isExposeProxy() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.isProxyTargetClass() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract org.springframework.aop.TargetSource org.springframework.aop.framework.Advised.getTargetSource() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.setPreFiltered(boolean) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.addAdvice(int,org.aopalliance.aop.Advice) throws org.springframework.aop.framework.AopConfigException 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.addAdvice(org.aopalliance.aop.Advice) throws org.springframework.aop.framework.AopConfigException 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.isPreFiltered() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract java.lang.Class[] org.springframework.aop.framework.Advised.getProxiedInterfaces() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.isInterfaceProxied(java.lang.Class) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract org.springframework.aop.Advisor[] org.springframework.aop.framework.Advised.getAdvisors() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract void org.springframework.aop.framework.Advised.removeAdvisor(int) throws org.springframework.aop.framework.AopConfigException 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.removeAdvisor(org.springframework.aop.Advisor) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.replaceAdvisor(org.springframework.aop.Advisor,org.springframework.aop.Advisor) throws org.springframework.aop.framework.AopConfigException 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract boolean org.springframework.aop.framework.Advised.removeAdvice(org.aopalliance.aop.Advice) 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract java.lang.String org.springframework.aop.framework.Advised.toProxyConfigString() 
2017-01-08 09:19:03 [main] DEBUG o.s.aop.framework.CglibAopProxy - Method is declared on Advised interface: public abstract java.lang.Class org.springframework.aop.TargetClassAware.getTargetClass() 
2017-01-08 09:19:03 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'anotherDAO' 

Когда метод является окончательным/окончательным, а класс DAO обозначен как @Component

2017-01-08 09:13:21 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Autowiring by type from bean name 'customDAO' via constructor to bean named 'getJdbcTemplate' 
2017-01-08 09:13:21 [main] DEBUG c.j.l.d.CustomDAO - Received JdbcTemplate: [email protected] 
2017-01-08 09:13:21 [main] INFO c.j.l.d.CustomDAO - Constructor Called 
2017-01-08 09:13:21 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'customDAO' to allow for resolving potential circular references 
2017-01-08 09:13:21 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor' 
2017-01-08 09:13:21 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'customDAO' 

Я до сих пор не могу понять, почему @Repository создает прокси-сервер и @Component пропускает его? Есть ли способ маркировать метод final и использовать @Repository на классе DAO?

При необходимости я могу создать отдельный вопрос для этого.

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