Spring框架中的容器以及两大特性

一、Spring框架的容器

  Spring容器提供了一种管理方法,致力于解决我们各个层级之间的对象的调用关系。


Spring容器

  我们通常调用各层级对象的时候,需要不断创建对象,一次访问就需要创建两个对象;如果我们使用Spring容器,将不同层级的对象放入容器中,每次使用的时候调用容器中的对象,就不用创建那么多对象,达到节约内存空间的目的。简单来讲,Spring容器就是存储JavaBean对象的容器。

创建BeanFactory的三种方式

  BeanFactory是一个接口,需要创建继承的子类对象。下图是其继承结构图:

BeanFactory接口的实现结构

方式一:使用XmlBeanFactory获取BeanFactory工厂类对象
  XmlBeanFactory需要传入一个配置文件的路径,这个配置文件就是我们spring的配置文件,默认是applicationContext.xml。这个方法已经过时,所以我们不再使用。

@Test
public void getUser() throws Exception{
    BeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
    Class<? extends BeanFactory> class1 = factory.getClass();
    System.out.println(class1);
}

方式二:使用ClassPathApplicationContext获取容器类
  这个方法替代了方式一,是我们创建容器类对象主要使用的方法。

@Test
public void getUser() throws Exception{
    BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
    System.out.println(factory.getClass());
}

方式三:使用FileSystemXmlApplicationContext来获取容器对象
  这种方式在创建对象的时候需要传入配置文件的绝对路径,这个方法可以使用项目外部的配置文件

@Test
public void getUser() throws Exception{
    BeanFactory factory = new FileSystemXmlApplicationContext("E:\\applicationContext.xml");
    System.out.println(factory.getClass());
}

二、Spring框架的第一大特性——IOC

  IOC(inversion of controller)指的是控制反转,简单来书,就是讲创建对象的过程或者创建对象的权限交给了spring框架来帮我们处理,我们不用再通过new的方式来创建JavaBean对象,这个过程就叫做IOC。

创建JavaBean对象的三种方法

首先创建一个JavaBean对象
package com.itheima.main;

public class User {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public void eat(){
        System.out.println(this.name+"正在吃饭");
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

}
方法一:使用默认构造创建JavaBean对象

首先在applicationContext中配置我们的对象

    <bean id="user" class="com.itheima.main.User">

    </bean>

然后从容器中获取我们的JavaBean对象

    @Test
    public void getBean() throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User bean = (User) context.getBean("user");
        bean.eat();
    
    }
方法二:使用静态工厂创建JavaBean对象

创建bean的工厂类

package com.itheima.main;

public class BeanFactory {

    public static User getBean(){
        
        return new User();
        
    }
}

在配置文件中进行配置

<bean id="user2" class="com.itheima.main.BeanFactory" factory-method="getBean">
    </bean>

获取JavaBean对象

    @Test
    public void getBean2() throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User bean = (User) context.getBean("user2");
        bean.eat();
    }
方式三:使用动态工厂创建JavaBean对象

创建工厂类的方式与上面相同
在配置文件中进行配置

    <bean id="createFactory" class="com.itheima.main.BeanFactory"></bean>
    <bean id="user3" factory-bean="createFactory" factory-method="getBean"></bean>

获取JavaBean对象

@Test
    public void getBean3() throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User bean = (User) context.getBean("user3");
        bean.eat();
    }

Bean的作用域和作用范围

Bean属性scope可以声明bean的作用域范围,Bean的作用域范围有四种:

  • Prototype:多例,每次调用都会创建一个新的实例
  • Singleton:单例,创建一个对象,每次调用都是用这个对象
  • Request:适用于web开发中,将我们的对象存储在request域对象中
  • Session:适用于web开发中,将我们的对象存储在session域对象中

JavaBean的生命周期

我们可以在JavaBean类中添加init-method与destroy-method两个方法,实现bean在初始化和关闭的时候调用的方法,然后在配置文件中进行配置。
JavaBean类

package com.itheima.main;

public class User {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    // 初始化方法
    public void initMethod() {
        System.out.println(this.name + "出生了");
    }

    public void eat() {
        System.out.println(this.name + "正在吃饭");
    }

    // 关闭方法
    public void destroyMethod() {
        System.out.println(this.name + "死亡了");
    }
}

配置文件

    <bean id="user" class="com.itheima.main.User" init-method="initmethod" destroy-method="destroymethod">

    </bean>

三、Spring框架的第二大特性——DI

  DI(dependency injection)指的是依赖注入,简单来说就是使用spring框架对我们的JavaBean对象赋值的过程。

1、使用setter方法进行赋值

使用上文中创建的JavaBean类
注意:一定要给属性生成对应的setter方法
配置JavaBean类的属性

    <bean id="user" class="com.itheima.main.User" init-method="initmethod" destroy-method="destroymethod">
        <property name="name" value="张三"></property>        
        <property name="age" value="20"></property>
    </bean>

从容器中获取我们的JavaBean对象

    @Test
    public void getBean() throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User bean = (User) context.getBean("user");
        bean.eat();
    
    }

2、使用构造器来申明JavaBean

在JavaBean中生成带所有属性的构造方法

public User() {
    super();
}

public User(String name,Integer age) {
    super();
    this.name = name;
    this.age = age;
}

在配置文件中申明JavaBean对象

    <bean id="user" class="com.itheima.main.User">
        <constructor-arg name="name" value="张三"></constructor-arg>
        <constructor-arg name="age" value="20"></constructor-arg>
    </bean>

申明的另一种方法:

<bean id="user" class="com.itheima.main.User">
    <constructor-arg index="0" type="java.lang.String" value="张三"></constructor-arg>
        <constructor-arg index="1" type="java.lang.Integer" value="20"></constructor-arg>
</bean>

调用JavaBean的属性

    @Test
    public void getBean() throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User bean = (User) context.getBean("user");
        bean.eat();
    
    }

3、P名称空间和C名称空间

  P名称空间与C名称空间其实都是不存在的虚拟空间,主要是用于简化我们的spring为JavaBean属性赋值时的配置。
添加P名称空间与C名称空间到schema

xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"

声明P名称空间和C名称空间

使用P名称空间和C名称空间简化我们的开发
  我们上面为属性赋值的时候可以通过setter方法或者构造方法进行赋值,下面可以对其进行简化

通过setter方法进行赋值:

    <bean id="user" class="com.itheima.main.User" >
        <property name="name" value="张三"></property>
        <property name="age" value="20"></property>
    </bean>

等价于:

    <bean id="user" class="com.itheima.main.User" p:name="张三" p:age="20">
    </bean>

通过构造方法进行赋值

    <bean id="user" class="com.itheima.main.User">
        <constructor-arg name="name" value="张三"></constructor-arg>
        <constructor-arg name="age" value="20"></constructor-arg>
    </bean>

等价于:

    <bean id="user" class="com.itheima.main.User" c:name="张三" c:age="20">
    </bean>

4、SPEL表达式

  Spel表达式,类似于jstl与el表达式的语言,spring可以支持我们在为属性赋值的时候,通过spel表达式来进行更改我们的属性值。


SPEL表达式

5、为集合属性赋值

创建一个含有集合属性的JavaBean类

package com.itheima.main;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class CollectProperty {
    private List list;
    private Set set;
    private Map map;
    private Properties properties;
    public List getList() {
        return list;
    }
    public void setList(List list) {
        this.list = list;
    }
    public Set getSet() {
        return set;
    }
    public void setSet(Set set) {
        this.set = set;
    }
    public Map getMap() {
        return map;
    }
    public void setMap(Map map) {
        this.map = map;
    }
    public Properties getProperties() {
        return properties;
    }
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
    
}

为集合属性注入值

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

推荐阅读更多精彩内容