spring(二)bean作用域、生命周期、spring依赖注入

本文详细介绍了Spring框架中Bean的作用域,包括singleton、prototype、request、session和globalSession,以及它们在不同场景下的适用性。此外,文章探讨了Bean的生命周期,包括初始化和销毁方法,以及BeanPostProcessor的使用。还讲解了依赖注入的两种方式:构造函数注入和设置值函数注入。最后,提到了Bean定义的继承和模板,以及如何通过XML配置文件引入外部properties配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

IOC之组件创建顺序

bean之间的依赖 depends-on 属性

默认情况下。bean对象创建的顺序,是从上到下 depends-on 可以设定依赖
bean对象:

public class A {
	public A() {
		System.out.println("A 被创建了");
	}
}
public class B {
	public B() {
		System.out.println("B 被创建了");
	}
}
public class C {
	public C() {
		System.out.println("C 被创建了");
	}
}

配置文件:

 <!-- 默认情况下。bean对象创建的顺序,是从上到下
                depends-on 可以设定依赖
         -->
    <bean id="a" class="com.zy.pojo.A" depends-on="b,c"/>
    <bean id="b" class="com.zy.pojo.B" />
    <bean id="c" class="com.zy.pojo.C" />

测试:
在这里插入图片描述

基于xml配置文件的自动注入

public class Car {
	private String carNo;
	private String name;

public class Person {

	private Car car;

	public Person(Car car) {
		this.car = car;
	}

配置文件:

 <bean id="car2" class="com.zy.pojo.Car">
        <property name="name" value="奔驰"/>
        <property name="carNo" value="京B2f453"/>
    </bean>
    <!--
    autowire 属性设置是否自动查找bean对象并给子对象赋值

    default 和 no 表示不自动查找并注入(你不赋值,它就null)
    byName 	是指通过属性名做为id来查找bean对象,并注入
                1、找到就注入
                2、找不到就为null
    byType  是指按属性的类型进行查找并注入  使用的set注入
                1、找到一个就注入
                2、找到多个就报错
                3、没有找到就为null
    constructor 是指按构造器参数进行查找并注入。
                1、先按照构造器参数类型进行查找并注入
                2、如果按类型查找到多个,接着按参数名做为id继续查找并注入。
                3、按id查找不到,就不赋值。
 -->

    <bean id="person" class="com.zy.pojo.Person" autowire="constructor">
        <property name="name" value="person"/>
    </bean>

测试:
在这里插入图片描述

Bean

Bean 定义

  被称作 bean 的对象是构成应用程序的支柱也是由 Spring IoC 容器管理的。bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。这些 bean 是由用容器提供的配置元数据创建的,例如,已经在先前章节看到的,在 XML 的表单中的 定义。

  bean 定义包含称为配置元数据的信息,下述容器也需要知道配置元数据:

      如何创建一个 bean

      bean 的生命周期的详细信息

      bean 的依赖关系

上述所有的配置元数据转换成一组构成每个 bean 定义的下列属性。
在这里插入图片描述

Bean的作用域

  创建一个bean定义,其实质是用该bean定义对应的类来创建真正实例的“配方”。把bean定义看成一个配方很有意义,它与class很类似,只根据一张“处方”就可以创建多个实例。不仅可以控制注入到对象中的各种依赖和配置值,还可以控制该对象的作用域。这样可以灵活选择所建对象的作用域,而不必在Java Class级定义作用域。Spring Framework支持五种作用域,分别阐述如下表。

  五种作用域中,request、sessionglobal session 三种作用域仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架),只能用在基于 web 的 Spring ApplicationContext 环境。

1. singleton——唯一 bean 实例

  当一个 bean 的作用域为 singleton,那么Spring IoC容器中只会存在一个共享的 bean 实例,并且所有对 bean 的请求,只要 id 与该 bean 定义相匹配,则只会返回bean的同一实例。 singleton 是单例类型(对应于单例模式),就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,但我们可以指定Bean节点的 lazy-init=”true” 来延迟初始化bean,这时候,只有在第一次获取bean时才会初始化bean,即第一次请求该bean时才初始化。 每次获取到的对象都是同一个对象。注意,singleton 作用域是Spring中的缺省作用域。要在XML中将 bean 定义成 singleton ,可以这样配置:

<bean id="ServiceImpl" class="com.zy.service.ServiceImpl" scope="singleton">

也可以通过 @Scope 注解(它可以显示指定bean的作用范围。)的方式

@Service
@Scope("singleton")
public class ServiceImpl{

}

2. prototype——每次请求都会创建一个新的 bean 实例

  当一个bean的作用域为 prototype,表示一个 bean 定义对应多个对象实例。 prototype 作用域的 bean 会导致在每次对该 bean 请求(将其注入到另一个 bean 中,或者以程序的方式调用容器的 getBean() 方法**)时都会创建一个新的 bean 实例。prototype 是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经验,对有状态的 bean 应该使用 prototype 作用域,而对无状态的 bean 则应该使用 singleton 作用域。** 在 XML 中将 bean 定义成 prototype ,可以这样配置:

<bean id="account" class="com.zy.DefaultAccount" scope="prototype"/>  
 或者
<bean id="account" class="com.zy.DefaultAccount" singleton="false"/> 

通过 @Scope 注解的方式实现就不做演示了。

3. request——每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效

  request只适用于Web程序,每一次 HTTP 请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效,当请求结束后,该对象的生命周期即告结束。 在 XML 中将 bean 定义成 request ,可以这样配置:

<bean id="loginAction" class=com.zy.LoginAction" scope="request"/>

4. session——每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效

  session只适用于Web程序,session 作用域表示该针对每一次 HTTP 请求都会产生一个新的 bean,同时该 bean 仅在当前 HTTP session 内有效.与request作用域一样,可以根据需要放心的更改所创建实例的内部状态,而别的 HTTP session 中根据 userPreferences 创建的实例,将不会看到这些特定于某个 HTTP session 的状态变化。当HTTP session最终被废弃的时候,在该HTTP session作用域内的bean也会被废弃掉。

<bean id="userPreferences" class="com.zy.UserPreferences" scope="session"/>

5. globalSession

  global session 作用域类似于标准的 HTTP session 作用域,不过仅仅在基于 portlet 的 web 应用中才有意义。Portlet 规范定义了全局 Session 的概念,它被所有构成某个 portlet web 应用的各种不同的 portle t所共享。在global session 作用域中定义的 bean 被限定于全局portlet Session的生命周期范围内。

<bean id="user" class="com.zy.Preferences "scope="globalSession"/>

Bean的生命周期

  对于单例的bean,生命周期有11个步骤:
1.instantiate bean对象实例化,bean对象实例化,是在加载配置文件的时候实例的。即,我们启动spring容器的时候,加载配置文件,此时就实例化bean了。
2.populate properties 封装属性
3.如果Bean实现BeanNameAware, 执行 setBeanName
4.如果Bean实现BeanFactoryAware 或者 ApplicationContextAware,设置工厂setBeanFactory 或者上下文对象 setApplicationContext
5.如果存在类实现 BeanPostProcessor(后处理Bean) ,执行postProcessBeforeInitialization(此点常常用来增强bean)
6.如果Bean实现InitializingBean 执行 afterPropertiesSet
7.调用 指定初始化方法 init
8.如果存在类实现 BeanPostProcessor(后处理Bean) ,执行postProcessAfterInitialization(此点常常用来增强bean)
9.执行业务处理
10.如果Bean实现 DisposableBean 执行 destroy
11.调用 指定销毁方法

initialization 和 destroy

  有时我们需要在Bean属性值set好之后和Bean销毁之前做一些事情,比如检查Bean中某个属性是否被正常的设置好值了。Spring框架提供了多种方法让我们可以在Spring Bean的生命周期中执行initialization和pre-destroy方法。

1.实现InitializingBean和DisposableBean接口

  这两个接口都只包含一个方法。通过实现InitializingBean接口的afterPropertiesSet()方法可以在Bean属性值设置好之后做一些操作,实现DisposableBean接口的destroy()方法可以在销毁Bean之前做一些操作。

例子如下:

public class GiraffeService implements InitializingBean,DisposableBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("执行InitializingBean接口的afterPropertiesSet方法");
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("执行DisposableBean接口的destroy方法");
    }
}

  这种方法比较简单,但是不建议使用。因为这样会将Bean的实现和Spring框架耦合在一起。

2.在bean的配置文件中指定init-method和destroy-method方法

  Spring允许我们创建自己的 init 方法和 destroy 方法,只要在 Bean 的配置文件中指定 init-method 和 destroy-method 的值就可以在 Bean 初始化时和销毁之前执行一些操作。

例子如下:

public class GiraffeService {
    //通过<bean>的destroy-method属性指定的销毁方法
    public void destroyMethod() throws Exception {
        System.out.println("执行配置的destroy-method");
    }
    //通过<bean>的init-method属性指定的初始化方法
    public void initMethod() throws Exception {
        System.out.println("执行配置的init-method");
    }
}

配置文件中的配置:

<bean name="giraffeService" class="com.giraffe.spring.service.GiraffeService" init-method="initMethod" destroy-method="destroyMethod">
</bean>

  需要注意的是自定义的init-method和post-method方法可以抛异常但是不能有参数。

这种方式比较推荐,因为可以自己创建方法,无需将Bean的实现直接依赖于spring的框架。

3.使用@PostConstruct和@PreDestroy注解

  除了xml配置的方式,Spring 也支持用 @PostConstruct@PreDestroy注解来指定 initdestroy 方法。这两个注解均在javax.annotation 包中。为了注解可以生效,需要在配置文件中定义org.springframework.context.annotation.CommonAnnotationBeanPostProcessor或context:annotation-config

例子如下:

public class GiraffeService {
    @PostConstruct
    public void initPostConstruct(){
        System.out.println("执行PostConstruct注解标注的方法");
    }
    @PreDestroy
    public void preDestroy(){
        System.out.println("执行preDestroy注解标注的方法");
    }
}

配置文件:

  
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />

总结

所以Spring Bean的生命周期是这样纸的:

  • Bean容器找到配置文件中 Spring Bean 的定义。
  • Bean容器利用Java Reflection API创建一个Bean的实例。
  • 如果涉及到一些属性值 利用set方法设置一些属性值。
  • 如果Bean实现了BeanNameAware接口,调用setBeanName()方法,传入Bean的名字。
  • 如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
  • 如果Bean实现了BeanFactoryAware接口,调用setBeanFactory()方法,传入BeanFactory对象的实例。
  • 与上面的类似,如果实现了其他*Aware接口,就调用相应的方法。
  • 如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessBeforeInitialization()方法
  • 如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。
  • 如果Bean在配置文件中的定义包含init-method属性,执行指定的方法。
  • 如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessAfterInitialization()方法
  • 当要销毁Bean的时候,如果Bean实现了DisposableBean接口,执行destroy()方法。
  • 当要销毁Bean的时候,如果Bean在配置文件中的定义包含destroy-method属性,执行指定的方法。

用图表示一下(图来源:http://www.jianshu.com/p/d00539babca5):

与之比较类似的中文版本:

  其实很多时候我们并不会真的去实现上面说描述的那些接口,那么下面我们就除去那些接口,针对bean的单例和非单例来描述下bean的生命周期:

单例管理的对象

  当scope=”singleton”,即默认情况下,会在启动容器时(即实例化容器时)时实例化。但我们可以指定Bean节点的lazy-init=”true”来延迟初始化bean,这时候,只有在第一次获取bean时才会初始化bean,即第一次请求该bean时才初始化。如下配置:

<bean id="ServiceImpl" class="com.zy.service.ServiceImpl" lazy-init="true"/>  

  如果想对所有的默认单例bean都应用延迟初始化,可以在根节点beans设置default-lazy-init属性为true,如下所示:

<beans default-lazy-init="true" >

  默认情况下,Spring 在读取 xml 文件的时候,就会创建对象。在创建对象的时候先调用构造器,然后调用 init-method 属性值中所指定的方法。对象在被销毁的时候,会调用 destroy-method 属性值中所指定的方法(例如调用Container.destroy()方法的时候)。写一个测试类,代码如下:

public class LifeBean {
    private String name;  

    public LifeBean(){  
        System.out.println("LifeBean()构造函数");  
    }  
    public String getName() {  
        return name;  
    }  

    public void setName(String name) {  
        System.out.println("setName()");  
        this.name = name;  
    }  

    public void init(){  
        System.out.println("this is init of lifeBean");  
    }  

    public void destory(){  
        System.out.println("this is destory of lifeBean " + this);  
    }  
}

life.xml配置如下:

<bean id="life_singleton" class="com.bean.LifeBean" scope="singleton" 
            init-method="init" destroy-method="destory" lazy-init="true"/>

测试代码:

public class LifeTest {
    @Test 
    public void test() {
        AbstractApplicationContext container = 
        new ClassPathXmlApplicationContext("life.xml");
        LifeBean life1 = (LifeBean)container.getBean("life");
        System.out.println(life1);
        container.close();
    }
}

运行结果:

LifeBean()构造函数
this is init of lifeBean
com.bean.LifeBean@573f2bb1
……
this is destory of lifeBean com.bean.LifeBean@573f2bb1

非单例管理的对象

  当scope=”prototype”时,容器也会延迟初始化 bean,Spring 读取xml 文件的时候,并不会立刻创建对象,而是在第一次请求该 bean 时才初始化(如调用getBean方法时)。在第一次请求每一个 prototype 的bean 时,Spring容器都会调用其构造器创建这个对象,然后调用init-method属性值中所指定的方法。对象销毁的时候,Spring 容器不会帮我们调用任何方法,因为是非单例,这个类型的对象有很多个,Spring容器一旦把这个对象交给你之后,就不再管理这个对象了。

为了测试prototype bean的生命周期life.xml配置如下:

<bean id="life_prototype" class="com.bean.LifeBean" scope="prototype" init-method="init" destroy-method="destory"/>

测试程序:

public class LifeTest {
    @Test 
    public void test() {
        AbstractApplicationContext container = new ClassPathXmlApplicationContext("life.xml");
        LifeBean life1 = (LifeBean)container.getBean("life_singleton");
        System.out.println(life1);

        LifeBean life3 = (LifeBean)container.getBean("life_prototype");
        System.out.println(life3);
        container.close();
    }
}

运行结果:

LifeBean()构造函数
this is init of lifeBean
com.bean.LifeBean@573f2bb1
LifeBean()构造函数
this is init of lifeBean
com.bean.LifeBean@5ae9a829
……
this is destory of lifeBean com.bean.LifeBean@573f2bb1

  可以发现,对于作用域为 prototype 的 bean ,其destroy方法并没有被调用。如果 bean 的 scope 设为prototype时,当容器关闭时,destroy 方法不会被调用。对于 prototype 作用域的 bean,有一点非常重要,那就是 Spring不能对一个 prototype bean 的整个生命周期负责:容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。 不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法。但对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责(让Spring容器释放被prototype作用域bean占用资源的一种可行方式是,通过使用bean的后置处理器,该处理器持有要被清除的bean的引用)。谈及prototype作用域的bean时,在某些方面你可以将Spring容器的角色看作是Java new操作的替代者,任何迟于该时间点的生命周期事宜都得交由客户端来处理。

  Spring 容器可以管理 singleton 作用域下 bean 的生命周期,在此作用域下,Spring 能够精确地知道bean何时被创建,何时初始化完成,以及何时被销毁。而对于 prototype 作用域的bean,Spring只负责创建,当容器创建了 bean 的实例后,bean 的实例就交给了客户端的代码管理,Spring容器将不再跟踪其生命周期,并且不会管理那些被配置成prototype作用域的bean的生命周期。

Bean的后置处理器BeanPostProcessor

后置处理器,可以在bean对象的初始化方法前/后,做一些工作。

后置处理器使用步骤:
1、编写一个类去实现BeanPostProcessor接口
2、到Spring容器配置文件中配置

public class MyBeanPostProcessor implements BeanPostProcessor {
    //初始化方法之后调用
    public Object postProcessBeforeInitialization(Object bean, String id) throws BeansException {
        System.out.println("初始化方法之前,正在初始化对象bean");
        if("p21".equals(id)){
            Person person = (Person) bean;
            person.setName("这个是我传入的值");
        }
        return bean;
    }
        //初始化方法之前带哦用
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化方法之前,正在初始化的对象bean");
        return bean;
    }
}

配置文件:

  <bean id="p21" class="com.zy.pojo.Person" init-method="intMethod" destroy-method="destroy">
        <property name="name" value="小脑斧"></property>
        <property name="car" ref="car2"></property>
    </bean>
<!--    配置自定义的后置处理器-->
    <bean class="com.zy.bean.MyBeanPostProcessor"/>

测试:
在这里插入图片描述

Spring Bean 定义继承

Bean 定义继承
  bean 定义可以包含很多的配置信息,包括构造函数的参数,属性值,容器的具体信息例如初始化方法,静态工厂方法名,等等。

子 bean 的定义继承父定义的配置数据。子定义可以根据需要重写一些值,或者添加其他值。

  Spring Bean 定义的继承与 Java 类的继承无关,但是继承的概念是一样的。你可以定义一个父 bean 的定义作为模板和其他子 bean 就可以从父 bean 中继承所需的配置。

当你使用基于 XML 的配置元数据时,通过使用父属性,指定父 bean 作为该属性的值来表明子 bean 的定义。

两个父子类

public class HelloWord {
    private String message1;
    private String message2;
 // setget略
    }
    
    public class HelloIndia {
    private String message1;
    private String message2;
    private String message3;}
    

applicationContext.xml:

<bean id="helloword" class="com.zy.bean.HelloWord">
        <property name="message1" value="helloword"></property>
        <property name="message2" value="helloword   second"></property>
    </bean>
    <bean id="helloIndia" class="com.zy.bean.HelloIndia" parent="helloword">
        <property name="message1" value="hello  india"></property>
        <property name="message3" value="hello  india   second"></property>
    </bean>

测试:
在这里插入图片描述  由此可以知道,bean继承了另一个bean,即使继承bean的对象没有赋值,也会继承父属性

Bean 定义模板

  你可以创建一个 Bean 定义模板,不需要花太多功夫它就可以被其他子 bean 定义使用。在定义一个 Bean 定义模板时,你不应该指定类的属性,而应该指定带 true 值的抽象属性,如下所示:

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

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

   <bean id="beanTeamplate" abstract="true">
      <property name="message1" value="Hello World!"/>
      <property name="message2" value="Hello Second World!"/>
      <property name="message3" value="Namaste India!"/>
   </bean>

   <bean id="helloIndia" class="com.tigger.HelloIndia" parent="beanTeamplate">
      <property name="message1" value="Hello India!"/>
      <property name="message3" value="Namaste India!"/>
   </bean>

</beans>

  父 bean 自身不能被实例化,因为它是不完整的,而且它也被明确地标记为抽象的。当一个定义是抽象的,它仅仅作为一个纯粹的模板 bean 定义来使用的,充当子定义的父定义使用。

Spring引入properties配置文件

db.properties

username=root
password=1234
driverClassName=com.mysql.jdbc.Driver
url =jdbc:mysql://localhost:3306/mybatis
initialSize=5
maxActive=10

applicationContext.xml:

 <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <!-- location属性设置你要加载的文件路径
                    classpath: 表示从类路径下搜索
        -->
        <property name="location" value="classpath:db.properties" />
    </bean>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${username}" />
        <property name="password" value="${password}" />
        <property name="driverClassName" value="${driverClassName}" />
        <property name="url" value="${url}" />
        <property name="initialSize" value="${initialSize}" />
        <property name="maxActive" value="${maxActive}" />
    </bean>

DI(依赖注入)

Spring框架的核心功能之一就是通过依赖注入的方式来管理Bean之间的依赖关系。

依赖注入
  每个基于应用程序的 java 都有几个对象,由这些对象一起工作来呈现出终端用户所看到的工作的应用程序。当编写一个复杂的 Java 应用程序时,应用程序类应该尽可能独立于其他 Java 类来增加这些类重用的可能性,并且在做单元测试时,测试独立于其他类的独立性。依赖注入(或有时称为布线)有助于把这些类粘合在一起,同时保持他们独立。

spring基于构造函数的依赖注入

Spring 基于构造函数的依赖注入
  当容器调用带有一组参数的类构造函数时,基于构造函数的 DI 就完成了,其中每个参数代表一个对其他类的依赖。

实体类:

public class TextEditor {
    private SpellChecker spellChecker;
    public TextEditor(SpellChecker spellChecker) {
        System.out.println("这是文本编辑器的构造器");
        this.spellChecker=spellChecker;
    }

    public TextEditor() {
    }
    public void check(){
        spellChecker.checkWork();
    }
}

public class SpellChecker {
    public SpellChecker() {
        System.out.println("这个是拼写检查的构造器");
    }
    public void checkWork(){
        System.out.println("拼写检查工作");
    }
}

配置文件;

<bean id="text" class="com.zy.bean.TextEditor">
        <constructor-arg ref="spell"/>
    </bean>
    <bean id="spell" class="com.zy.bean.SpellChecker"/>

测试:
在这里插入图片描述构造函数参数解析:
  如果存在不止一个参数时,当把参数传递给构造函数时,可能会存在歧义。要解决这个问题,那么构造函数的参数在bean定义中的顺序就是把这些参数提供给适当的构造函数的顺序就可以了。考虑以下的类:

package x.y;
public class Foo {
   public Foo(Bar bar, Baz baz) {
      // ...
   }
}

先前配置文件工作顺利:

<beans>
   <bean id="foo" class="x.y.Foo">
      <constructor-arg ref="bar"/>
      <constructor-arg ref="baz"/>
   </bean>

   <bean id="bar" class="x.y.Bar"/>
   <bean id="baz" class="x.y.Baz"/>
</beans>

  让我们再检查一下我们传递给构造函数不同类型的位置。考虑以下的类:

package x.y;
public class Foo {
   public Foo(int year, String name) {
      // ...
   }
}

  如果您使用type属性显式的指定了构造函数参数的类型,容器也可以使用与简单类型匹配的类型。


<beans>

   <bean id="exampleBean" class="examples.ExampleBean">
      <constructor-arg type="int" value="2001"/>
      <constructor-arg type="java.lang.String" value="Zara"/>
   </bean>

</beans>

  最后和也是最好的传递构造函数参数的方式,使用索引属性来显式的指定构造函数参数的索引。下面是基于索引为0的示例,如下所示:

<beans>

   <bean id="exampleBean" class="examples.ExampleBean">
      <constructor-arg index="0" value="2001"/>
      <constructor-arg index="1" value="Zara"/>
   </bean>

</beans>

  最后,如果你想要向一个对象传递一个引用,你需要使用 标签的ref属性,如果你想要直接传递值,那么你应该使用如上所示的值属性。

spring基于设置值函数的依赖注入

  当容器调用一个无参的构造函数或一个无参的静态工厂方法来初始化你的bean后,通过容器在你的bean上调用设置值函数,基于设置值函数的DI就完成了。

public class TextEditor {
    private SpellChecker spellChecker;
    public TextEditor(SpellChecker spellChecker) {
        System.out.println("这是文本编辑器的构造器");
        this.spellChecker=spellChecker;
    }

    public TextEditor() {
    }
    public void check(){
        spellChecker.checkWork();
    }
    public SpellChecker getSpellChecker(){
        return spellChecker;
    }

    public void setSpellChecker(SpellChecker spellChecker) {
        this.spellChecker = spellChecker;
    }
}

applicationContext.xml

<bean id="text1" class="com.zy.bean.TextEditor">
       <property name="spellChecker" ref="spell1"/>
    </bean>
    <bean id="spell1" class="com.zy.bean.SpellChecker"/>

  应该注意定义在基于构造函数注入和基于设置值函数注入中的Beans.xml文件的区别。唯一的区别就是在基于构造函数注入中,我们使用的是 标签中的 元素,而在基于设立值函数的注入中,我们使用的是 标签中的 元素。

  第二个你需要注意的点是,如果你要把一个引用传递给一个对象,那么你需要使用 标签的ref属性,而如果你要直接传递一个值,那么你应该使用值属性。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值