春天@Autowired不工作

时间:2010-11-26 18:48:04

标签: spring spring-mvc annotations autowired

我有一些自动注释的问题。我的应用程序如下所示:

这是控制器:

@Controller
public class MyController {
    @Autowired
    @Qualifier("someService")
    private SomeService someService;

    ....
}

这是一个服务层:

public interface SomeService {
    ...
}

@Service
public class SomeServiceImpl implements SomeService{    
    @Autowired
    @Qualifier("myDAO")
    private MyDAO myDAO;

    ....
}

和DAO层:

public interface MyDAO{
    ....        
}

@Repository
public class JDBCDAOImpl implements MyDAO {    
    @Autowired
    @Qualifier("dataSource")
    private DataSource dataSource;    
    ....
}

这是app-service.xml文件:

....
<bean id="propertyConfigurer"
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
      p:location="/WEB-INF/jdbc.properties" />

<bean id="dataSource"
      class="org.springframework.jdbc.datasource.DriverManagerDataSource"
      p:driverClassName="${jdbc.driverClassName}"
      p:url="${jdbc.url}"
      p:username="${jdbc.username}"
      p:password="${jdbc.password}"/>

<bean id="SomeService" class="com.service.SomeServiceImpl" />    
<bean id="myDAO" class="com.db.JDBCDAOImpl" />    

所以...当我启动一个web-app时,MyController自动正确(SomeServiceImpl类对象正确注入someService字段),但someService的myDAO feild为null值(未正确注入)。

你能帮我找个问题吗?

P.S。它很有意思,但是当我将myDAO中的“bean id”更改为另一个(例如myDAO2)时,系统会给我一个错误,因为bean myDAO不存在而无法进行注入。那么,Spring注射,但它在哪里?为什么它不能正常工作?

7 个答案:

答案 0 :(得分:10)

我找到了解决方案。正如Javi所说(非常感谢你,Javi),我必须使用@Repository@Service注释来注释DAO和服务层类。现在我试着这样写:

@Service("someService")
public class SomeServiceImpl implements SomeService{    
    @Autowired
    @Qualifier("myDAO")
    private MyDAO myDAO;

    ....
}

@Repository("myDAO")
    public class JDBCDAOImpl implements MyDAO {    
    @Autowired
    @Qualifier("dataSource")
    private DataSource dataSource;    
    ....
}

一切正常!!!

但是我仍然没有找到这个问题的答案:如果应用程序将更复杂,并且将具有更复杂的结构,其中@Repositore@Service注释不是某些类的首选,如何正确注入bean,它位于较低级别(在类的字段中或在类的字段中)(当然,带有@Autowire注释)?

答案 1 :(得分:4)

我想你需要<context:annotation-config />

答案 2 :(得分:2)

您可以使用

<context:component-scan base-package="PATH OF THE BASE PACKAGE"/>  
配置.xml文件中的

条目。此条目将扫描/读取java类中所有声明的类型和注释。

答案 3 :(得分:0)

重要点:

  1. 有时,@ Component可能会导致出现一个问题,即可能会提示找不到默认构造函数。 定义为@Component批注的类,它必须具有默认的构造函数。
  2. 假设,我们在用户定义的类引用的字段上应用了@Autowired注释。 现在,如果我们也将@Component应用于该类,则它将始终使用null初始化。 因此,具有@Autowired的字段的类定义中不应包含@Component。
  3. 默认情况下,@ Autowired是byType。

地址Bean在学生班级自动接线。 让我们看看如果在Address.java上应用@Component会发生什么。

CollegeApp.java:

+----+--------+------------+----------------+
| id | region |   date1    | neareast_early |
+----+--------+------------+----------------+
|  1 | a      | 2017-01-01 |                |
|  2 | a      | 2017-01-07 | 2017-01-01     |
|  3 | a      | 2017-03-03 | 2017-01-07     |
|  4 | a      | 2017-04-03 | 2017-03-03     |
|  5 | b      | 2017-02-02 |                |
|  6 | b      | 2017-02-28 | 2017-02-02     |
+----+--------+------------+----------------+

我们希望将Elgin街与学生地址自动连线。

Address.java:

$( ".f_best" ).click(function(){

  if ($('.productTable').has('.quality_class_a')) {
    $('.productTable tr').has('.quality_class_a').toggle();
  }



});

Student.java:

        <dt class="uk-text-muted"></dt>
          <dd class="quality_class_a">
              <img src="/test/img/icons/A.png" alt="Kvaliteediklass: Parim (OEM vastav)"/>
              <span class="tooltiptext">Kvaliteediklass: Parim (OEM vastav)</span>
          </dd>
        <b>Mann-filter CUK31003</b>
                                                                             <br />
        <span class="additionalInfo">
                                        <!--<b>Lisainfo:</b> -->Pikkus (mm): 311 | Laius (mm): 220 | Kõrgus (mm): 31 | Filtritüüp: Aktiivsöefilter<span class="264289555_277655395_d"></span>
                      </span>
      </td>
                                                                                                                          <td class="stock-list-price">
            <table class="stock-list-category">
                        <tr class="stock-list-category-item  green-tr " style="display: table-row!important;">
              <td>
                                          POL02
                                    </td>
              <td>L 11 aug  </td>
              <td class="price ">
                  26,91€
              </td>
          </tr>
                          </table>
        </td>
    </tr>

输出:-名称:null年龄:0地址:null //地址此处未自动接线。

要解决此问题,请仅按以下方式更改Address.java:

Address.java:

package com.myTest
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.bean.Address;
import com.bean.Student;
//Component scanning will for only those classes
//which is defined as @Component. But, all the class should not use
//@Component always even if the class is enabled with auto
//component scanning, specially the class which is Autowired
//Or which is a property of another class 
@Configuration
@ComponentScan(basePackages={"com.bean"})
public class CollegeApp {
    @Bean
    public Address getAddress(){
        return new Address("Elgin street");
}
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(CollegeApp.class);
        Student student=context.getBean(Student.class);
        System.out.println(student.toString());
        context.close();
    }
}

输出:- 名称:无年龄:0地址:埃尔金街

答案 4 :(得分:0)

您应该在spring-config.xml中加入XML代码的这一部分:

<context:component-scan base-package="Fully.Qualified.Package.Name" />

但是您应该知道<context:annotation-config><context:component-scan>之间的区别,因为大多数人都建议这两个:

1)两个标签之间的第一个大区别是:<context:annotation-config>用于在应用程序上下文中已注册的bean中激活应用的注释。请注意,bean是否通过哪种机制注册都没有关系,例如使用<context:component-scan>或在application-context.xml文件本身中定义。

2)第二个差异是由第一个差异本身驱动的。它确实在上下文中注册了bean,并且还扫描了bean内部的注释并激活它们。所以<context:component-scan>;做<context:annotation-config>的工作,但是它还会扫描软件包并在应用程序上下文中注册Bean。

答案 5 :(得分:0)

有两个原因。

  1. 未对注入的对象进行注释或未使用正确的@ Service / @ Component / @ Repository注释对服务进行注释时。

  2. 确定了第1点后,接下来请检查带注释的服务类的类包是否包含在主类中的spring boot应用程序的类路径中。您可以使用以下注释。

@SpringBootApplication(scanBasePackages = { “ com.ie.efgh.somepackage”,“ com.ie.abcd.someotherpackage”})

这样做是要告诉spring在类加载期间检查类的包。

答案 6 :(得分:-2)

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- Specifying base package of the Components like Controller, Service, 
        DAO -->
    <context:component-scan base-package="com.jwt" />

    <!-- Getting Database properties -->
    <context:property-placeholder location="classpath:application.properties" />

    <!-- DataSource -->
    <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
        id="dataSource">
        <property name="driverClassName" value="${database.driver}"></property>
        <property name="url" value="${database.url}"></property>
        <property name="username" value="${database.user}"></property>
        <property name="password" value="${database.password}"></property>
    </bean>

    <!-- Hibernate SessionFactory -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            </props>
        </property>
    </bean>

</beans>