2018-11-18-spring-bean标签

480 阅读5分钟

创建方式

  1. 使用默认构造函数进行创建
    • 在spring的配置文件中使用bean标签,配以id与class属性的之后,并且没有其他属性与标签时。采用的就是默认无参构造进行创建对象,如果此时没有无参构造则无法创建对象。

1


  1. 使用普通工厂中的方法创建对象,也可以称之为使用某个类的方法创建对象,并存入spring容器
    2
    简单地说就是id=unlimitedName01标签达到的功能就是在核心容器中获取key为unlimitedName01的value时,会先寻找到factory-bean的value指定的另一个bean标签,根据寻找到的这个标签,spring就会知道用_哪一个_工厂对象,而factory-method对应的value会让spring知道调用刚才寻找到工厂的_哪一个_方法!,所以在使用工厂的时候,spring最少配置两个bean标签。

  1. 使用静态工厂中的静态方法创建对象(或者说是使用某个类中的静态方法创建对象存入容器)

总结:除了配置文件的写法不同,以上三种方式在java代码中取出spring核心容器里面id对应的value方式完全相同。如取出静态工厂中生产的对象:

import cn.dx.service.impl.SaveServiceImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SaveServlet {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
        SaveServiceImpl staticFactory = classPathXmlApplicationContext.getBean("staticFactory", SaveServiceImpl.class);
        staticFactory.save();
    }
}

以上的动态工厂与静态工厂中使用new造成耦合的原因是,为了演示方便工厂类都可以看做是jar包中的类,jar包中的类都是别人写的,我们都是不能改的,因为jar包中的类都是.class文件不是.java文件。当我们需要jar包中某个类的返回值存入spring容器中的时候就需要用到上面的2,3的方式。
工厂模式只能降低耦合,不能消除耦合


bean的作用范围

  • bean对象默认都是单例的
  • bean的scope属性可以用来指定bean的作用范围
    • 取值:1.singleton : 单例的(默认值) 2.prototype : 多例的 3. request : 作用于web应用的请求范围 4. session:作用于web应用的会话范围 5.global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境时,这个就是session。常用的为1,2项。

bean对象的生命周期

  • 单例对象
    • 出生:当spring核心容器创建时单例对象出生ClassPathXmlApplicationContext
    • 活着:只要容器还在对象就在
    • 死亡:容器销毁,对象消亡
    • 总结:单例对象的生命周期和容器相同

package cn.dx.servlet;

import cn.dx.service.impl.SaveServiceImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 创建bean的三种方式
 * 第一种方式:使用默认构造函数的方式进行创建
 *
 */
public class SaveServlet {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
        SaveServiceImpl staticFactory = classPathXmlApplicationContext.getBean("serviceSave", SaveServiceImpl.class);
        staticFactory.save();
        //以为main线程执行结束后程序结束,还来不及调用容器的销毁方法,main方法就从内存中消失了,类似于线程直接中断,所以想到看到容器销毁需要
        //手动调用容器的销毁方法
        classPathXmlApplicationContext.close();
    }
}
  • 多例对象

多例对象有个很有趣的点,只是变更xml的scope配置,会发现,单例对象销毁容器会调用的destroy方法,在多例模式创建对象的时候却没有调用destroy方法。

  • 多例对象生命周期
    • 出生:当我们需要使用核心容器中的对象时,对象出生(这一点与BeanFactory创建多例对象的策略一致)
    • 活着:对象使用时一直存在
    • 死亡: GC垃圾回收之后(即没有任何栈内存空间指向的时候),spring并不知道对象是么时候用完,只能由GC进行对象销毁。

依赖注入 Dependency Injection

  • IOC的作用:削减(降低)程序(类与类)之间的依赖关系,所以既然是削减,那么依赖关系一定是存在的。耦合也叫做依赖关系。此时的依赖关系的管理就交给spring来维护
  • 什么叫做依赖关系呢?
    • 在当前类中需要用到其他类的对象时,由spring为我们提供,要想达到此种效果,只需要在spring的配置文件中告诉spring我们需要用哪个类就行了。
    • 依赖关系的维护,我们就称之为依赖注入
依赖注入的类型

一共有三类

  1. 基本类型和String
  2. 其他bean类型(在配置文件中或者注解配置过的bean)
  3. 复杂类型也叫集合类型
注入的方法-三种
  1. 使用构造函数提供
    • 其实核心为了弥补在一开始,使用控制反转创建对象的时候不能向构造函数传值的问题。
package cn.dx.service.impl;

import cn.dx.service.SaveServiceInterface;

import java.util.Date;

public class SaveServiceImpl implements SaveServiceInterface {
    private String x;
    private Integer y;
    private Date z;

    public SaveServiceImpl(String x, Integer y, Date z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    @Override
    public String toString() {
        return "SaveServiceImpl{" +
                "x='" + x + '\'' +
                ", y=" + y +
                ", z=" + z +
                '}';
    }

    public void save() {
        System.out.println("调用dao层");
        System.out.println(this);
    }
    public void init(){
        System.out.println("初始化生命周期被调用了");
        System.out.println(this);
    }
    public void destroy(){
        System.out.println("销毁方法被调用了");
    }
}


<constructor> 优势:在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功
弊端:改变bean对象的实例化方式,是我们在创建对象时,如果用不到这些数据也必须提供。在实际开发中除了避无可避必须使用这种方式进行依赖注入的时候,其他时间是不采用这种方式的!而是采用set方式
2. 使用set方法提供

优势:创建对象没有明确的限制,可以直接注入(赋值使用)
弊端:如果有某个成员必须有值,则获取对象时有可能需要值得那个set方法没有执行
两个方法各有利弊(利弊相反)更常用(往往)的方式是set
3. 使用注解提供

复杂类型的注入(数组,List,Set,Map,Properties)

需要注意一点,name的值就是对应属性的名字。

结构相同的标签可以进行互换 所以我们只要记住一个List结构的标签与一个Map结构的标签就够了!