当我在配置文件中使用bean定义以及使用@Autowire注释

时间:2018-03-30 16:38:21

标签: java spring

我正在查看一些现有的应用程序代码,由于那里的代码,我很困惑,这里是场景:

在课程ABC中,我将自动装配为:

@Autowired
RestTemplate restTemplate;

然后在我的spring bean配置文件中,我将bean定义为:

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/>

在班级ABC中,我使用的是休息模板:

restTemplate.postForObject(url, requestObject, String.class);

我的问题是:

  • 当我使用其余模板时,我使用的对象是因为自动装配还是bean配置文件中定义的对象?
  • 如果是自动装配,因为我没有指定范围,所以它将是单身,对吧?

<小时/> 根据评论和答案,下面是简约的可重现代码,它表明即使我在bean配置文件中进行了自动布线和bean定义,我也可以运行该程序并且没有问题。

主要课程:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class SpringTest {

    @Autowired
    Person person;

    public static void main(String[] args) {
        generalTest();
    }

    private static void generalTest() {
        testApplicationContext();
    }

    private static void testApplicationContext() {
        ApplicationContext applicationContext = new FileSystemXmlApplicationContext("bean.xml");

        SpringTest springTest = (SpringTest) applicationContext.getBean("springTest");

        if(springTest.person == null){
            System.out.println("person is NULL");
        } else{
            System.out.println("person is not NULL");
        }

    }

}

Bean文件:

<?xml version = "1.0" encoding = "UTF-8"?>

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

    <context:component-scan base-package="com.learn.stackoverflow.general"/>
    <!-- as such below is useless because The use of <context:component-scan> implicitly enables the functionality of <context:annotation-config>. 
    There is usually no need to include the <context:annotation-config> element when using <context:component-scan>. -->
    <context:annotation-config /> 

   <bean id = "person" class = "com.learn.stackoverflow.general.Person" scope="singleton">
   </bean>

</beans>

人员类:

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope(value="singleton")
public class Person implements InitializingBean, Human {
    @Autowired
    SpringTest springTest;

    static{
        System.out.println("Static initialization from Person");
    }

    {
        System.out.println("Instance initialization  from Person");
    }

    public Person(){
        System.out.println("Constructor  from Person");
    }

    public void sayHello(){
        System.out.println("Hello");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean.afterPropertiesSet  from Person");
    }

    @Override
    public void breathe() {
        System.out.println("person is breathing...");
    }

}

输出为person is not NULL

3 个答案:

答案 0 :(得分:2)

配置文件告诉Spring 创建一个ID为&#34; restTemplate&#34;其类型为org.springframework.web.client.RestTemplate。默认范围是bean的单个实例。

然后在代码中,由于存在一个类型 RestTemplate的bean,所以bean(其ID恰好为&#34; restTemplate&#34;是自动连接的。

&#34; restTemplate&#34;作为id或类属性,也有&#34; restTemplate&#34;因为它的名字并不重要。豆可以注入,因为它是相同类型的。 (并且因为那里只有1种类型。)

答案 1 :(得分:1)

@Autowired不创建bean,它将采用与预期类型匹配的现有bean声明并将其放在字段中。在XML中你有你的bean声明,没有它你的bean将不存在(除非你使用Spring Boot,在这种情况下它可能会自动创建,如果它不存在)。

自JSR-299以来,您现在可以使用@Inject而不是@Autowired,如果您有最新版本的Spring和javax.inject依赖项。两者都完全相同,但@Inject更清晰。

答案 2 :(得分:0)

当IoC容器找到bean配置文件中定义的bean定义时,会使用相同的定义来注入实例,如果IoC容器找不到,那么它会创建一个实例并注入相同的内容。

下面是一个稍微调整过的示例,它演示了上述概念,您可以使用它来评论和取消注释bean配置文件中提到的bean定义。 请仔细阅读我的代码评论。

<强> SpringTest:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class SpringTest {
    @Autowired
    Person person;

    public static void main(String[] args) {
        generalTest();
    }

    private static void generalTest() {
        testApplicationContext();
    }

    private static void testApplicationContext() {
        ApplicationContext applicationContext = new FileSystemXmlApplicationContext("C:\\E_Drive\\Projects\\Workspace\\Test\\CS101\\src\\com\\learn\\stackoverflow\\general\\bean.xml");
        SpringTest springTest = (SpringTest) applicationContext.getBean("springTest");

        if(springTest.person == null){
            System.out.println("person is NULL");
        } else{
            System.out.println("person is not NULL");
            springTest.person.sayHello(); // here output will be “Hello, ppj” if you keep the config file bean definition and when you remove that bean definition then output is “Hello, null”
        }

    }
}

Bean配置:

<?xml version = "1.0" encoding = "UTF-8"?>

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

    <context:component-scan base-package="com.learn.stackoverflow.general"/>

    <!-- once you get comment out below, IoC will instatiate a bean and will inject the same in SpringTest's autowiring of Person class  -->
   <!-- <bean id = "person" class = "com.learn.stackoverflow.general.Person" scope="singleton">
      <constructor-arg name="name" value="ppj"></constructor-arg>
   </bean> -->

</beans>

<强>人:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope(value="singleton")
public class Person {
    private String name;

    @Autowired
    SpringTest springTest;

    public Person(){
        System.out.println("Constructor from Person");
    }

    public Person(String name){
        System.out.println("String Constructor from Person");
        this.name = name;
    }

    public void sayHello(){
        System.out.println("Hello, " + name);
    }

}