Java程序员从笨鸟到菜鸟之(七十)细谈Spring(三)IOC和spring基本配置详解

本文详细解析Spring框架中的IoC与依赖注入概念,包括构造器注入、设值注入、接口注入以及自动装配策略。同时,阐述了Spring Bean的生命周期管理,从容器实例化Bean、依赖注入、初始化到销毁的全过程。并通过XML配置文件示例,展示如何配置Bean的生存范围、初始化方法、销毁方法以及抽象与继承关系。最后,简述Spring Bean在应用上下文中的生命周期与在Bean工厂中的区别。

对于IoC的一些知识点,相信大家都知道他在Spring框架中所占有的地位,应该可以算的上是核心之一吧,所以IOC是否理解清楚,决定了大家对Spring整个框架的理解

Ioc的理解

spring的两个核心概念:一个是控制反转IoC,也可以叫做依赖注DI。还有一个是面向切面编程AOP

控制反转:当某个java对象需要(依赖)另一个java对象时,不

是自身直接创建依赖对象,而是由实现IoC的容器(如spring框架的IoC容器)来创建,并将它注入需要这个依赖对象的java对象中。

spring的容器

spring管理的基本单元是Bean,在spring的应用中,所有的组件都是一个个的Bean,它可以是任何的java对象。spring负责创建这些Bean的实例。并管理生命周期。而spring框架是通过其内置的容器来完成Bean的管理的,Bean在spring的容器中生存着,使用时只需要通过它提供的一些方法从其中获取即可。

spring的容器有两个接口:BeanFactory和ApplicationContext这两个接口的实例被陈为spring的上下文。

ApplicationContext ac = newClassFathXmlApplicationContext("app*.xml");
AccountService accountService =(AccountService)ac.getBean("accountServiceImpl");


注:由于ApplicationContext是基于BeanFactory之上的,所以,一般ApplicationContext功能比较强大,建议使用

ApplicationContext经常用到的三个实现:

1.ClassPathXmlApplicationContext:从类路径中的XML文件载入上下文定义信息。把上下文定义文件当成类路径资源。

2.FileSystemXmlApplicationContext:从文件系统中的XML文件载入上下文定义信息。

3.XmlWebApplicationContext:从Web系统中的XML文件载入上下文定义信息。

一:spring的依赖注入

1)、构造器注入

<bean id="accoutDaoImpl" class="cn.csdn.dao.AccoutDaoImpl"
scope=”singleton”/>
<bean id="accoutServicImpl"
class="cn.csdn.service.AccoutServicImpl" scope=”">
<!-- 构造方法注入方式-->
<constructor-arg ref="accoutDaoImpl"/>
</bean>

这种注入方式很少用,如果是注入对象一般为上例注入,但有时要注入基本数据类型,一般用下面方法注入

<constructor-arg>
<value>hello world!</value>
</constructor-arg>

如果构造方法不只一个参数时,应指明所注入参数的索引或者数据类型,例如:

<constructor-arg index="0" type="java.lang.String">
<value>sunDriver</value>
</constructor-arg>
<constructor-arg index="1" type="java.lang.String">
<value>jdbc:odbc:School</value>
</constructor-arg>

2)、设值(set方法)注入

<bean id="accountDaoImpl"
class="cn.csdn.dao.AccoutDaoImpl"/>
<bean id="accoutServicImpl"
class="cn.csdn.service.AccoutServicImpl">
<!-- 设值(set 方法)注入-->
<property name="accountDaoImpl" ref="accoutDaoImpl"/>
</bean>

注:<propertyname="accountDaoImpl"ref="accoutDaoImpl"/>

相当于调用setAccountDaoImpl方法,把值设为accoutDaoImpl

3)接口注入(很少用)

二:xml装配Bean属性含义

1.id:指定该Bean的唯一标识。

2.class:指定该Bean的全限定名。

3.name:为该Bean指定一到多个别名。多个别名可以用“,”和“;”分割。

4.autowire:指定该Bean的属性的装配方式。

所谓自动装配是指在<BEAN>标签中不用指定其依赖的BEAN,而是通过配置的自动装配来自动注入依赖的BEAN,这种做法让我们的配置更加简单

1no:不使用自动装配。必须通过ref元素指定依赖,这是默认设置。由于显式指定协作者可以使配置更灵活、更清晰,因此对于较大的部署配置,推荐采用该设置。而且在某种程度上,它也是系统架构的一种文档形式。

<bean id="bean1" class="cn.csdn.service.Bean1"
scope="singleton">
<property name="studentDaoImpl"
ref="studentDaoImpl">
</property>
</bean>

备注:有property属性指定ref

2byName:根据属性名自动装配。此选项将检查容器并根据

名字查找与属性完全一致的bean,并将其与属性自动装配。例如,在

bean定义中将autowire设置为byname,而该bean包含master属性(同时提供setMaster(..)方法),Spring就会查找名为master的bean定义,并用它来装配给master属性。

<beanid="bean1"class="cn.csdn.service.Bean1"

scope="singleton"autowire="byName"/>

备注:没有property属性

3byType:果容器中存在一个与指定属性类型相同的

bean,那么将与该属性自动装配。如果存在多个该类型的bean,那么

将会抛出异常,并指出不能使用byType方式进行自动装配。若没有找到相匹配的bean,则什么事都不发生,属性也不会被设置。如果你不希望这样,那么可以通过设置dependency-check="objects"让Spring抛出异常。

备注:spring3.0以上不抛异常。

<beanid="bean1"class="cn.csdn.service.Bean1"

scope="singleton"autowire="byType"/>

备注:没有property属性

4Constructor:与byType的方式类似,不同之处在于它应用

于构造器参数。如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。

<beanid="bean1"class="cn.csdn.service.Bean1"

scope="singleton"autowire="constructor"/>

备注:没有property属性

5autodetect:通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的

构造器,那么将使用byType方式。

<beanid="bean1"class="cn.csdn.service.Bean1"

scope="singleton"autowire="autodetect"/>

5.scope:指定该Bean的生存范围

scope用来声明IOC容器中的对象应该处的限定场景或者说该对象的存活空间,即在IOC容器在对象进入相应的scope之前,生成并装配这些对象,在该对象不再处于这些scope的限定之后,容器通常会销毁这些对象。

1)singleton类型bean定义,在一个容器中只存在一个实例,所有对该类型bean的依赖都引用这一单一实例

2)scopeprototypebean,容器在接受到该类型的对象的请求的时候,会每次都重新生成一个新的对象给请求方,虽然这种类型的对象的实例化以及属性设置等工作都是由容器负责的,但是只要准备完毕,并且对象实例返回给请求方之后,容器就不在拥有当前对象的引用,请求方需要自己负责当前对象后继生命周期的管理工作,包括该对象的销毁

3)requestsessionglobalsession

这三个类型是spring2.0之后新增的,他们只适用于web程序,通常是和XmlWebApplicationContext共同使用

request

<beanid="requestPrecessor"class="...RequestPrecessor"scope="request"/>

Spring容器,即XmlWebApplicationContext会为每个HTTP请求创建一个全新的RequestPrecessor对象,当请求结束后,,该对象的生命周期即告结束

session

<beanid="userPreferences"class="...UserPreferences"scope="session"/>

Spring容器会为每个独立的session创建属于自己的全新的UserPreferences实例,他比requestscopebean会存活更长的时间,其他的方面真是没什么区别。

globalsession:

<beanid="userPreferences"class="...UserPreferences"scope="globalsession"/>

globalsession只有应用在基于porlet的web应用程序中才有意义,他映射到porlet的global范围的session,如果普通的servlet的web应用中使用了这个scope,容器会把它作为普通的session的scope对待。

6.init-method:指定该Bean的初始化方法。destroy-method:指定该Bean的销毁方法。这个就像servletinitdestroy方法一样,只不过这里在配置文件配置的

7.abstract:指定该Bean是否为抽象的。如果是抽象的,则

spring不为它创建实例。

8.parent

如果两个Bean的属性装配信息很相似,那么可以利用继

承来减少重复的配置工作。

<!--装配Bean的继承

父类作为模板,不需要实例化,设置abstract=”true”-->

`<beanid=”parent”class=”cn.csdn.service.Parent”

abstract=”true”>

<propertyname=”name”value=”z_xiaofei168”/>

<propertyname=”pass”value=”z_xiaofei168”/>

</bean>

<!--装配Bean的继承

子类中用parent属性指定父类标识或别名

子类可以覆盖父类的属性装配,也可以新增自己的属性装配

-->

`<beanid=”child”class=”cn.csdn.service.Chlid”

parent=”parent”>

<propertyname=”pass”value=”123123”/>

<propertyname=”age”value=”22”/>

</bean>

三:装配Bean的各种类型属性值

1..简单类型属性值的装配

<bean id="bean1" class="cn.csdn.domain.Bean1">
<property name="name" value="z_xiaofei168"/>
<property name="age">
<value>22</value>
</property>
</bean>

2.引用其他Bean的装配

<bean id="bean1" class="cn.csdn.domain.Bean1">
...
</bean>
<bean id="bean2" class="cn.csdn.domain.Bean2">
<!-- 引用自其他Bean 的装配-->
<property name="bean1" ref="bean1"/>
</bean>

另外一种不常使用的配置方式是在property元素中嵌入

一个bean元素来指定所引用的Bean.

<bean id="bean1" class="cn.csdn.domain.Bean1">
...
</bean>
<bean id="bean2" class="cn.csdn.domain.Bean2">
<!-- 引用自其他Bean 的装配-->
<property name="bean1">
<bean id="bean1"
class="cn.csdn.domain.Bean1"/>
</property>
</bean>

3.集合的装配

其实集合的装配并不是复杂,反而感觉到很简单,用一个例子来说明问题吧:


package com.bebig.dao.impl;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import com.bebig.dao.UserDAO;
import com.bebig.model.User;
public class UserDAOImpl implements UserDAO {
    private Set<String> sets;
    private List<String> lists;
    private Map<String, String> maps;
    private Properties props;
    public Set<String> getSets() {
        return sets;
    }
    public void setSets(Set<String> sets) {
        this.sets = sets; }
    public List<String> getLists() {
        return lists; }
    public void setLists(List<String> lists) {
        this.lists = lists;  }
    public Map<String, String> getMaps() {
        return maps;
    }
    public void setMaps(Map<String, String> maps) {
        this.maps = maps;
    }
    public Properties getProps() {
        return props;
    }
    public void setProps(Properties props) {
        this.props = props;
    }
    public void save(User u) {
        System.out.println("a user saved!");
    }
    @Override
    public String toString() {
        return "sets.size:" + sets.size() + " lists.size:" + lists.size()
                + " maps.size:" + maps.size() + " props.size:" + props.size();
    }
}


配置如下:

<?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"
     >
    <!-- a service object; we will be profiling its methods -->
    <bean name="u" class="com.bebig.dao.impl.UserDAOImpl">
        <!-- set -->
        <property name="sets">
            <set>
                <value>1</value>
                <value>2</value>
            </set>
        </property>
        <!-- list -->
        <property name="lists">
            <list>
                <value>a</value>
                <value>b</value>
            </list>
        </property>
        <!-- map -->
        <property name="maps">
            <map>
                <entry key="1" value="aa"></entry>
                <entry key="2" value="bb"></entry>
            </map>
        </property>
        <!-- properties -->
        <property name="props">
            <props>
                <prop key="a">haha</prop>
                <prop key="b">hi</prop>
            </props>
        </property>
    </bean>
    <bean id="userService" class="com.bebig.service.UserService"
        scope="prototype">
        <constructor-arg>
            <ref bean="u" />
        </constructor-arg>
    </bean>
    <!-- this switches on the load-time weaving -->
    <!-- <context:load-time-weaver /> -->
</beans>


四:Springbean生命周期

在传统的Java应用中,Bean的生命周期非常简单。Java的关键词new用来实例化Bean(或许他是非序列化的)。这样就够用了。相反,Bean的生命周期在Spring容器中更加细致。理解SpringBean的生命周期非常重要,因为你或许要利用Spring提供的机会来订制Bean的创建过程。

bean生命周期

1.容器寻找Bean的定义信息并且将其实例化。

2.受用依赖注入,Spring按照Bean定义信息配置Bean的所有属性。

3.如果Bean实现了BeanNameAware接口,工厂调用BeansetBeanName()方法传递BeanID

4.如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。

5.如果BeanPostProcessorBean关联,那么它们的postProcessBeforeInitialzation()方法将被调用。

6.如果Bean指定了init-method方法,它将被调用。

7.最后,如果有BeanPsotProcessorBean关联,那么它们的postProcessAfterInitialization()方法将被调用。

到这个时候,Bean已经可以被应用系统使用了,并且将被保留在BeanFactory中知道它不再需要。

有两种方法可以把它从BeanFactory中删除掉。

1.如果Bean实现了DisposableBean接口,destory()方法被调用。

2.如果指定了订制的销毁方法,就调用这个方法。

BeanSpring应用上下文的生命周期与在Bean工厂中的生命周期只有一点不同,唯一不同的是,如果Bean实现了ApplicationContextAwre接口,setApplicationContext()方法被调用。

只有singleton行为的bean接受容器管理生命周期。

non-singleton行为的beanSpring容器仅仅是new的替代,容器只负责创建。

对于singletonbeanSpring容器知道bean何时实例化结束,何时销毁,Spring可以管理实例化结束之后,和销毁之前的行为,管理bean的生命周期行为主要未如下两个时机:

Bean全部依赖注入之后

Bean即将销毁之前

1)依赖关系注入后的行为实现:

有两种方法:A.编写init方法B.实现InitializingBean接口

afterPropertiesSetinit同时出现,前者先于后者执行,使用init方法,需要对配置文件加入init-method属性

2bean销毁之前的行为

有两种方法:A.编写close方法B.实现DisposableBean接口

destroyclose同时出现,前者先于后者执行,使用close方法,需要对配置文件加入destroy-method属性

总体上分只为四个阶段

1.BeanFactoyPostProcessor实例化

2.Bean实例化,然后通过某些BeanFactoyPostProcessor来进行依赖注入

3.BeanPostProcessor的调用.Spring内置的BeanPostProcessor负责调用Bean实现的接口:BeanNameAware,BeanFactoryAware,ApplicationContextAware等等,等这些内置的BeanPostProcessor调用完后才会调用自己配置的BeanPostProcessor

4.Bean销毁阶段

注:xml依赖注入中的bean.xml例子:

<?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-2.5.xsd">
  <bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl">
  </bean>
  <bean id="userService" class="com.bjsxt.service.UserService">
  	<!-- 
  	<property name="userDAO" ref="u" />
  	 -->
  	 <constructor-arg>
  	 	<ref bean="u"/>
  	 </constructor-arg>
  </bean>
</beans>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值