创建方式
- 使用默认构造函数进行创建
- 在spring的配置文件中使用bean标签,配以id与class属性的之后,并且没有其他属性与标签时。采用的就是默认无参构造进行创建对象,如果此时没有无参构造则无法创建对象。
- 使用普通工厂中的方法创建对象,也可以称之为使用某个类的方法创建对象,并存入spring容器 简单地说就是id=unlimitedName01标签达到的功能就是在核心容器中获取key为unlimitedName01的value时,会先寻找到factory-bean的value指定的另一个bean标签,根据寻找到的这个标签,spring就会知道用_哪一个_工厂对象,而factory-method对应的value会让spring知道调用刚才寻找到工厂的_哪一个_方法!,所以在使用工厂的时候,spring最少配置两个bean标签。
- 使用静态工厂中的静态方法创建对象(或者说是使用某个类中的静态方法创建对象存入容器)
总结:除了配置文件的写法不同,以上三种方式在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(); }}复制代码
- 多例对象
- 多例对象生命周期
- 出生:当我们需要使用核心容器中的对象时,对象出生(这一点与BeanFactory创建多例对象的策略一致)
- 活着:对象使用时一直存在
- 死亡: GC垃圾回收之后(即没有任何栈内存空间指向的时候),spring并不知道对象是么时候用完,只能由GC进行对象销毁。
依赖注入 Dependency Injection
- IOC的作用:削减(降低)程序(类与类)之间的依赖关系,所以既然是削减,那么依赖关系一定是存在的。耦合也叫做依赖关系。此时的依赖关系的管理就交给spring来维护
- 什么叫做依赖关系呢?
- 在当前类中需要用到其他类的对象时,由spring为我们提供,要想达到此种效果,只需要在spring的配置文件中告诉spring我们需要用哪个类就行了。
- 依赖关系的维护,我们就称之为依赖注入。
依赖注入的类型
一共有三类
- 基本类型和String
- 其他bean类型(在配置文件中或者注解配置过的bean)
- 复杂类型也叫集合类型
注入的方法-三种
- 使用构造函数提供
- 其实核心为了弥补在一开始,使用控制反转创建对象的时候不能向构造函数传值的问题。
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. 使用注解提供