10

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

这是控制器:

@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" />    

所以......当我启动一个网络应用程序时,MyController Autowires 正确(由 SomeServiceImpl 类对象正确注入的 someService 字段),但 someService 的 myDAO 字段具有空值(未正确注入)。

你能帮我找出问题吗?

PS 这很有趣,但是当我将“bean id”从 myDAO 更改为另一个(例如 myDAO2)时,系统给了我一个错误,无法完成注入,因为 bean myDAO 不存在。那么,Spring 进行了一次注入,但是它在哪里呢?为什么它不能正常工作?

4

7 回答 7

13

我找到了解决方案。正如 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;    
    ....
}

一切正常!!!

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

于 2010-11-26T19:21:57.767 回答
4

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

于 2010-11-26T18:59:29.703 回答
3

您可以使用

<context:component-scan base-package="PATH OF THE BASE PACKAGE"/>  

配置 .xml 文件中的条目。此条目将扫描/读取 java 类中所有声明的类型和注释。

于 2013-09-23T09:11:25.083 回答
1

要点:

  1. 有时,@Component 可能会导致一个问题,它可能会说没有找到默认构造函数。定义为@Component 注解的类,它必须有一个默认构造函数。
  2. 假设我们在用户定义的类引用的字段上应用了@Autowired 注释。现在,如果我们也将 @Component 应用到该类,那么它将始终被初始化为 null。因此,带有@Autowired 的字段在其类定义中不应有@Component。
  3. 默认情况下,@Autowired 是 byType。

地址 bean 在学生类中自动装配。让我们看看如果我们在 Address.java 中应用 @Component 会发生什么。

CollegeApp.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();
    }
}

我们希望 Elgin 街道与学生地址自动连接。

地址.java:

package com.bean;
import org.springframework.stereotype.Component;
@Component
public class Address {
    private String street;
    public Address()
    {
    }
    public Address(String theStreet)
    {
        street=theStreet;
    }
    public String toString()
    {
        return (" Address:"+street);
    }
}

学生.java:

package com.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Student {
    private String name;
    private int age;
    private Address address;
    public Student()
    {
    }
    public Student(String theName,int theAge)
    {
        name=theName;age=theAge;
    }
    @Autowired
    public void setAddress(Address address) {
        this.address = address;
    }
    public String toString()
    {
        return ("Name:"+name+" Age:"+age+ " "+address);
    }
}

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

要解决此问题,只需更改 Address.java 如下:

地址.java:

package com.bean;
public class Address {
    private String street;
    public Address(String theStreet)
    {
        street=theStreet;
    }
    public String toString()
    {
        return (" Address:"+street);
    }
}

输出:- 姓名:空 年龄:0 地址:埃尔金街

于 2018-08-08T16:57:41.060 回答
0

这可能有两个原因。

  1. 当您没有使用正确的 @Service/@Component/@Repository 注释注释注入的对象或说服务时。

  2. 一旦您确定了第 1 点,接下来检查您的注释服务类的类包是否包含在主类中 Spring Boot 应用程序的类路径中。您可以使用以下注释进行配置。

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

这样做你告诉 spring 在类加载期间查看类的包。

于 2020-12-17T13:49:06.130 回答
0

您应该将这部分 XML 代码包含在spring-config.xml

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

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

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

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

于 2020-03-29T18:23:19.097 回答
-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>
于 2018-04-13T09:56:43.697 回答