Spring @Autowired не работает

у меня есть некоторые проблемы с autowire аннотации. Мое приложение выглядит так:

вот контроллер:

@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;    
    ....
}

Это приложение-сервис.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" />    

так... Когда я запускаю веб-приложение, Mycontroller Autowires правильно (поле someService правильно введено объектом класса SomeServiceImpl), но MyDao feild someService имеет нулевое значение (не вводится правильно).

не могли бы вы помочь мне найти проблему?

P.S. Это интересно, но когда я меняю "bean id" с myDAO на какой-то другой (например, myDAO2), система дает мне ошибку, что инъекция не может быть выполнена, потому что bean myDAO не существует. Итак, весной делают укол, но где он? И почему это не работает правильно?

5 ответов


Я нашел решение. Как сказал Хави (большое спасибо за вас, Хави), я должен аннотировать классы DAO и Service layer с аннотациями @Repository и @Service. Теперь я попытался написать так:

@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 аннотации не предпочтительны для некоторых классов, как правильно вводить бобы, которые расположены на более низких уровнях (в полях классов, или в поле полей классов) (с аннотацией @Autowire, конечно)?


Я думаю, вам нужно <context:annotation-config />.


You can use 
<context:component-scan base-package="PATH OF THE BASE PACKAGE"/>  entry your configuration .xml file. This entry will scan/read all the stareo type af annotations from the java classes .

важные моменты 1) Иногда @Component может привести к проблеме, когда он может сказать, что конструктор по умолчанию не найден. Класс, который определен как аннотация @Component, должен иметь конструктор по умолчанию. 2) Предположим, мы применили аннотацию @Autowired в поле, которое является пользовательской ссылкой на класс. Теперь, если мы также применяем @Component к этому классу, он всегда будет инициализирован с null. Таким образом, поле с @Autowired не должно иметь @Component в своем определении класса. 3) по по умолчанию @Autowired - byType.

address bean автоматически подключается к классу студентов. Посмотрим,что произойдет, если мы применим @Component по адресу.Ява.

  • CollegeApp.java

пакета com.образом: mytest;
импорт организации.springframework.контекст.аннотация.Помощью annotationconfigapplicationcontext;
импорт организации.springframework.контекст.аннотация.Боб;
импорт организации.springframework.контекст.аннотация.ComponentScan;
импорт орг.springframework.контекст.аннотация.Конфигурация;
импортировать com.фасоль.Адрес;
импортировать com.фасоль.Студент;
// Сканирование компонентов будет только для этих классов
//который определяется как @Component. Но, весь класс не должен использовать
// @Component всегда, даже если класс включен с auto
// сканирование компонентов, особенно класса, который является Autowired
//Или который является свойством другого класса
@Configuration
@ComponentScan (basePackages={"com.bean"})
public class CollegeApp {
@ Bean
публичный адрес getAddress(){
вернуть новый адрес ("улица Элгина");
}
public static void main (String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(CollegeApp.класс);
Студент студент=контекст.getBean(студент.класс);
Система.из.метод println(студент.toString ());
контекст.close();
}
}

мы хотим, чтобы Элгин-стрит была autowired со студенческим адресом.

  • адрес.java

пакета com.Боб;
импорт организации.springframework.стереотип.Компонент;
@ Component
адрес публичного класса {
частная струнная улица;
public Address ()
{
}
общественный Адрес(строка theStreet)
{
улица=theStreet;
}
public String toString ()
{
возврат ("Адрес:" + улица);
}
}

  • студент.java

пакета com.Боб;
импорт организации.springframework.зернышки.фабрика.аннотация.Autowired;
импорт организации.springframework.стереотип.Компонент;
@ Component
студент публичного класса {
частный Имя строки;
частная инт возраста;
частный адрес адрес;
public Student ()
{
}
public Student (String theName,int theAge)
{
имя=имя;возраст=theAge;
}
@ Autowired
public void setAddress (адрес адреса) {
этот.адрес = адрес;
}
public String toString ()
{
возврат ("имя:" + имя+ " возраст:" + возраст+ " "+адрес);
}
}

вывод: - имя: null Возраст:0 Адрес: null //адрес не Autowired здесь.

чтобы решить проблему, измените только адрес.java, как показано ниже.

  • адрес.java

пакета com.Боб;
адрес публичного класса {
частная струнная улица;
публичный адрес(строка theStreet)
{
улица=theStreet;
}
общественный String toString ()
{
возврат ("Адрес:" + улица);
}
}

выход:-
Имя: null Возраст:0 Адрес: Elgin street


<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>