重温Spring笔记2 - bean的应用

一、bean的实例化

Bean的实例化有基于XML和基于注解。其中基于XML实例化的有类构造器实例化、静态工厂方法实例化、实例工厂方法实例化。

1、创建spring配置

在xml文件中声明Bean时,spring配置文件的根元素是来源于spring beans命名空间所定义的<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"
       xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"
       >

</beans>

2、Bean的实例化 — 类构造器实例化(这里以一个歌手为例子)

  • 创建一个Person接口,该接口有一个perform()方法
public interface Person {
    public void perform();
}
  • 创建一个Singer类,实现Person接口
public class Singer implements Person {
    @Override
    public void perform() {
        System.out.println("我是歌手,喜欢唱歌");
    }
}
  • 实例化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"
       xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    <bean id="singer" class="com.chensr.test.Singer"></bean>
</beans>

  • 写测试类
public class Test {
    @org.junit.Test
    public void test(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring-context.xml");
        Person singer = (Person)ac.getBean("singer");
        singer.perform();
    }
}

右键点击run Test,即可看到控制台输出“我是歌手,喜欢唱歌”,则表明类构造器实例化成功

3、Bean的实例化 — 静态工厂方法实例化

  • 创建一个PersonFactory工厂类,该接口有一个getSinger()方法
public class PersonFactory {
    public static Person getSinger(){
        return  new Singer();
    }
}
  • 修改配置文件,添加bean配置(id是必须唯一)

<bean id="singer" class="com.chensr.test.PersonFactory" factory-method="getSinger"></bean>

右键点击run Test,即可看到控制台输出“我是歌手,喜欢唱歌”,则表明静态工厂方法实例化成功

4、Bean的实例化 — 实例工厂方法实例化

  • 修改personFactory工厂类(去掉getSinger()方法关键字static
public class PersonFactory {
    public  Person getSinger(){
        return  new Singer();
    }
}
  • 修改配置文件相关的bean配置

<bean id="personFactory" class="com.chensr.test.PersonFactory"></bean>
<bean id="singer" factory-bean="personFactory" factory-method="getSinger"></bean>

右键点击run Test,即可看到控制台输出“我是歌手,喜欢唱歌”,则表明实例工厂方法实例化成功

5、Bean的实例化 — 基于注解实例化

      spring引人了组件自动扫描机制,它可以在类路径底下寻找标注了@Component@service@Controller@Repository注解的类,并把这些类纳入spring容器中管理。它的作用和XML文件中使用bean节点配置组件是一样的。使用它需要开启<context:component-scan>,它包含了<context:annotation-config>的内容。默认情况下spring会查找使用了@Component@Service@Controller@Repository注解的类。其中,@Service用于标注业务层组件,@Controller用于标注控制层组件,@Repository用于标注数据库访问组件,@Component标注不好归类的组件(也就是说什么类都可以标注)。其实,目前四个注解是没有区别的。

  • 修改spring-context.xml,添加context命名空间,并且配置自动扫描

<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-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"
       default-lazy-init="true">
    
    <!-- 使用annotation 自动注册bean, 并保证@Required、@Autowired的属性被注入 -->
    <context:component-scan base-package="com.chensr">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" />
    </context:component-scan>
</beans>

  • Singer类添加注解,即加上@Service
@Service("singer")
public class Singer implements Person {
    @Override
    public void perform() {
        System.out.println("我是歌手,喜欢唱歌");
    }
}
  • 测试类
public class Test {
    @org.junit.Test
    public void test(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring-context.xml");
        Person singer = (Person)ac.getBean("singer");
        singer.perform();
    }
}
  • 运行结果:我是歌手,喜欢唱歌

注:一般情况是,我们都是用类构造器实例化或基于注解实例bean

 

二、Bean的作用域

   1)singleton:单实例作用域,这是Spring容器默认的作用域,使用singleton作用域生成的是单实例,在整个Bean容器中仅保留一个实例对象供所有调用者共享引用。单例模式对于那些无会话状态的Bean(如辅助工具类、DAO组件、业务逻辑组件等)是最理想的选择。

   2)prototype:原型模式,这是多实例作用域,针对每次不同的请求,Bean容器均会生成一个全新的Bean实例以供调用者使用。prototype作用域非常适用于那些需要保持会话状态的Bean实例,有一点值得注意的就是,Spring不能对一个prototype Bean的整个生命周期负责,容器在初始化、装配好一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。因此,客户端要负责prototype实例的生命周期管理。

   3)request:针对每次HTTP请求,Spring容器会根据Bean的定义创建一个全新的Bean实例,且该Bean实例仅在当前HTTP request内有效,因此可以根据需要放心地更改所建实例的内部状态,而其他请求中根据Bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。当处理请求结束,request作用域的Bean实例将被销毁。该作用域仅在基于web的Spring ApplicationContext情形下有效。

   4)session:针对某个HTTP Session,Spring容器会根据Bean定义创建一个全新的Bean实例,且该Bean实例仅在当前HTTP Session内有效。与request作用域一样,我们可以根据需要放心地更改所创建实例的内部状态,而别的HTTP Session中根据Bean定义创建的实例,将不会看到这些特定于某个HTTP Session的状态变化。当HTTP Session最终被废弃的时候,在该HTTP Session作用域内的Bean实例也会被废弃掉。该作用域仅在基于Web的Spring ApplicationContext情形下有效。

   5)global session:该作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的Web应用中才有意义。portlet规范定义了全局Session的概念,它被所有构成某个portlet Web应用的各种不同的portlet所共享。在global session作用域中定义的Bean被限定于全局portlet Session的生命周期范围内。如果我们是在编写一个标准的基于Servlet的Web应用,并且定义了一个或多个具有global session作用域的Bean,系统会使用标准的HTTP Session作用域,并且不会引起任何错误。该作用域仅在基于Web的Spring ApplicationContext情形下有效

例子:

  • 配置bean实例:

<bean id="singer" class="com.chensr.test.Singer"></bean>

  • 修改测试类
public class Test {
    @org.junit.Test
    public void test(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring-context.xml");
        Person singer1 = (Person)ac.getBean("singer");
        Person singer2 = (Person)ac.getBean("singer");

        System.out.println(singer1==singer2);
    }
} 
  • 输出结果为 true ,表明spring默认情况是单例模式
  • 此时修改配置文件

<bean id="singer" class="com.chensr.test.Singer" scope="prototype"></bean>

  • 重新运行,输出结果为false

注:request、session、global session三种作用域在开发中用得很少

 

三、Bean的生命周期

1、通过构造器或者工厂方式创建bean实例

2、为bean的属性设置值和对其他bean引用

3、调用bean的初始化方法

4、使用bean

5、当容器关闭时,调用bean的销毁方法

 

  • Bean实例化时间

  默认情况下,单例(singleton)在容器实例化时就被实例化,多例(prototype)只有在调用getBean()方法时被实例化。但可以通过lazy-inti属性改变单例实例化时间。

例子:

1)修改Singer方法,添加无参构造器

public class Singer implements Person {

    Singer(){
        System.out.println("构造歌手类");
    }

    @Override
    public void perform() {
        System.out.println("我是歌手,喜欢唱歌");
    }
}

2)修改配置文件

<bean id="singer" class="com.chensr.test.Singer"></bean>

3)修改Test测试类

public class Test {
    @org.junit.Test
    public void test(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring-context.xml");
    }
}

运行结果:构造歌手类 

4)此时如果修改配置文件,设置为延迟加载

<bean id="singer" class="com.chensr.test.Singer" lazy-init="true"></bean>

运行结果没有输出任何内容

注:lazy-init属性对应多例实例是不起作用的。其注解关键词@Lazy(false)

  • init-method destroy-method

  这两个属性分别是用于bean实例化后执行的方法和bean销毁前执行的方法。下面举个例子,如何让一个歌手进场后高喊“我来了”,在离场前说“白白”。

1)修改Singer,添加enter()、sayGoodBye()两个方法

public class Singer implements Person {

    Singer(){
        System.out.println("构造歌手类");
    }

    @Override
    public void perform() {
        System.out.println("我是歌手,喜欢唱歌");
    }

    @Override
    public void enter() {
        System.out.println("哈喽,我来了");
    }

    @Override
    public void sayGoodBye() {
        System.out.println("白白");
    }
}

2)修改配置文件,添加init-method和destroy-method属性

<bean id="singer" class="com.chensr.test.Singer" init-method="enter" destroy-method="sayGoodBye"></bean>

3)修改Test测试类

public class Test {
    @org.junit.Test
    public void test(){
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("spring-context.xml");
        Person singer = (Person)ac.getBean("singer");
        singer.perform();
        ac.destroy();
    }
}

4)运行结果:

         构造歌手类

         哈喽,我来了

         我是歌手,喜欢唱歌

         白白

  • 注意:
  • init-method destroy-method对应的注解分别是@PostConstruct@PreDestroy
  • ApplicationContext并没有提供相应的关闭容器的方法,所以在Test测试类中,初始化容器时,用ClassPathXmlApplicationContext接收



Done


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值