(FS计划)Spring的IoC容器对bean的实例化

首先,加载bean需要先写好配置文件(其实用注解也可以,只是不方便理解)

配置

<beans>
    <!--导入其他资源XML-->
    <import resource=”resource1.xml”/>
    <!--Bean定义,class定义Bean的实现类,id称为标识符,其余id为别名-->
    <bean id=”bean1”class=””></bean>
    <bean id=”bean2”class=””></bean>
<!--指定name,这样name就是“标识符”-->
<bean name=”bean2”class=””></bean>
    <!--alias为bean指定别名-->
    <alias alias="bean3" name="bean2"/>
    <!--导入其他依赖-->
    <import resource=”resource2.xml”/>
</beans>

多个配置文件是可以编制成数组,交给ApplicationContext加载的。
但是大家现在用习惯了注解

SpringMVC的IoC容器中,管理的bean 内部表示为BeanDefinition

一个bean需要以下属性

  • 全限定类名(FQN):用于定义Bean的实现类;
  • Bean行为定义:这些定义了Bean在容器中的行为;包括作用域(单例、原型创建)、是否惰性初始化及生命周期等;
  • Bean创建方式定义:说明是通过构造器还是工厂方法创建Bean;
  • Bean之间关系定义:即对其他bean的引用,也就是依赖关系定义,这些引用bean也可以称之为同事bean 或依赖bean,也就是依赖注入。

bean使用时必须有一个唯一的指定:
id必须唯一不可重复,一个bean可以有多个id,其余的id是别名;
没有id可以用唯一不重复的name,若有需要可以使用alias来指定别名,或者用,隔开;
同时指定id和name,id就是标识符,而name就是别名,总之必须在IoC容器中唯一;
若id和name都没有指定,则bean在使用的时候会使用全限定的类名进行注入。

实例化

SpringMVC是通过反射来实例化bean的。
1.通过构造器实例化bean:
Spring IoC容器即能使用默认空构造器也能使用有参数构造器两种方式创建Bean,无参数的直接在XML文件中直接定义bean节点,带参数的可以在XML文件中bean节点下增加constructor-arg参数属性:

<bean name="test" class="com.zing.test.HelloMvc">
<!-- 指定构造器参数 -->
    <constructor-arg index="0" value="第一个参数"/>
</bean>

index是参数所在的位置,value表示注入常量值,也可以指定引用,指定引用使用ref来引用另一个Bean定义,当然注入还可以根据参数类型和名字来配置

<!-- 根据变量名注入 -->
    <constructor-arg name="testIoC" value="第一个参数"/>
<!-- 根据参数类型注入-->
    <constructor-arg type="java.lang.String" value="第一个参数"/>
<!--构造器里注入另一个bean-->
<!-- 通过构造器注入 -->
<bean id="helloApi" class="com.zing.test.NormalBean"/>
<bean id="bean2" class="com.zing.test.TestProperty">
    <property name="helloApi"><ref bean=" helloApi"/></property>
</bean>

2.使用静态工厂来实例化bean
需要编写工厂方法,这样实例化的时候即可使用工厂方法来实例化bean

package com.zing.test.factory_test;

import com.zing.test.hello.HelloImpl;
//工厂类
public class HelloIoCFactory {
    public static HelloImpl newInstance(String name) {
        System.out.println(name);
        return new HelloImpl(name);
    }
}

第一种工厂配置

<!--为bean配置工厂方法-->
<bean class="com.zing.test.factory_test.HelloIoCFactory" id="helloIoC" factory-method="newInstance">
    <constructor-arg index="0" value="哈哈"/>
</bean>

第二种工厂配置

<bean id="instanceFactory" class="com.zing.test.factory_test.HelloIoCFactory"/>
<bean id="byIndex" factory-bean="instanceFactory"  factory-method="newInstance">
    <constructor-arg index="0" value="Hello World!"/>
    <constructor-arg index="1" value="1"/>
</bean>
//通过工厂获取实例
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config.xml");
HelloInterface hello = beanFactory.getBean("helloIoC",HelloImpl.class);
hello.sayHello();

3.通过setter方法进行注入
个人觉得:有必要吗?都是用注解的好不好,就列一下,不详细记录了

<!-- 通过setter方式进行依赖注入 -->
    <bean id="bean" class="com.zing.test.factory_test.HelloImpl4">
        <property name="message" value="Hello World!"/>
        <property name="index">
            <value>1</value>
        </property>
    </bean>

4.延时实例化
延时初始化又叫惰性初始化,作用是消除资源占用巨大的bean在程序初始化时的影响,防止因为这个bean,导致启动缓慢。延迟初始化的Bean通常会在第一次使用时被初始化;
配置如下:

<!-- 通过配置lazy-init="true"实现惰性初始化 -->
<bean id="helloApi" class="com.zing.test.HelloImpl" lazy-init="true"/>

自动装配

自动装配就是指由Spring来自动地注入依赖对象,无需人工参与。

目前Spring3.0支持nobyNamebyTypeconstructor四种自动装配,默认是“no”指不支持自动装配的,其中Spring3.0已不推荐使用之前版本的autodetect自动装配,推荐使用Java 5+支持的(@Autowired)注解方式代替;

<bean id="helloApi" class="com.zing.test.HelloImpl"/>
<bean id="bean" class="com.zing.test.bean.HelloApiDecorator" autowire="byName"/>
  • byName使用setter方法根据参数名称注入
  • 根据类型注入,在根据类型注入时,将把当前自己排除在外!如果是ListMap这样的类型,用autowire-candidate属性为false来让指定的Bean放弃作为自动装配的候选者。使用primary属性为true来指定某个Bean为首选Bean
  • constructor构造器注入,只用在构造器中。
  • autodetect自动匹配,不推荐使用!

不是所有的类型都支持自动匹配,Object、基本数据类型(Date、CharSequence、Number、URI、URL、Class、int不支持
<bean>标签的autowire-candidate属性可被设为false,这个bean将不能作为可依赖注入的参数
数组类型、集合(Set、Collection、List)接口类型:将根据泛型获取匹配的所有候选者并注入到数组或集合中
字典(Map)接口类型:同样根据泛型信息注入,键必须为String类型的Bean名字,值根据泛型信息获取

缺点

如果你用的是自动装配的话,出了问题会比较难找。不知道是哪里注入进来的,唉,这就是我等菜比为什么要先从配置开始看。现在流行用注解,会好不少。

依赖检查

用于检查Bean定义的属性都注入数据了,不管是自动装配的还是配置方式注入的都能检查,如果没有注入数据将报错,从而提前发现注入错误,只检查具有setter方法的属性。
对于注解来说没什么用,简单介绍一下

<bean id="test"/>
<!-- 注意我们没有注入,所以测试时会报错 -->
<bean id="bean" dependency-check="objects">
  <property name="message" value="Haha"/>
</bean>

dependency-check配置检查类型,一共有4种:null,object,simple,all
null=不检查,为默认配置。
object=检查除基本类型外的依赖对象。
simple=对基本类型进行依赖检查,包括数组类型,其他依赖不报错;
all=所有类型都检查


FS全栈计划目录:https://micorochio.github.io/fs-plan/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容