海创软件组-20200405-Spring 核心之IoC(一)

目录

Spring IoC容器的两个接口
依赖注入的类型
Bean的配置

…IOC:控制反转依赖注入。它使程序组件或类之间尽量形成一种松耦合的结构,开发者在使用类的实列之前,需要先创建对象的实列。而IoC是将创建实列的任务交给了IOC容器,这样在开发应用代码的时候只需要直接使用类的实列,而不需要再创建实列。


Spring IoC容器的两个接口

…pring IoC容器的设计主要是基于BeanFactory和ApplicationContext两个接口。ApplicationContext和BeanFactory的区别在于对Bean的创建时机不同。BeanFactory在初始化的时候,不会被创建,而是在真正获取对象的时候会被创建。ApplicationContext会将其中的所有Bean对象进行创建(即不用的也会被创建)。

1)BeanFactory
BeanFactory ctx=new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
 //通过容器获取配置中的hellospring(id)的实列
 Student hello=(Student) ctx.getBean("helpspring");
2)ApplicationContext

…ApplicationContext扩展了BeanFactory容器并添加了对I18N、生命周期事件的发布监听等更加强大的功能。ApplicationContext接口有三个实现类,可以实例化其中任何一个类来创建Spring的ApplicationContext容器。

①ClassPathXmlApplicationContext(将从类路径目录中寻找指定的XML配置文件)

//spring容器初始化,加载applicationContext.xml文件的两种:
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
//通过容器获取配置中的hellospring(id)的实列
       Student hello=(Student) ctx.getBean("helpspring");     

②FileSystemXmlApplicationContext(从指定文件的绝对路径中寻找XML配置文件,找到并装载完成ApplicationContext的实例化工作)

 //使用spring的配置文件来创建相应的实列来使用
 //spring容器初始化,加载applicationContext.xml文件
ApplicationContext ctx=new FileSystemXmlApplicationContext("E:/applicationContext.xml");
//通过容器获取配置中的hellospring(id)的实列
Student hello=(Student) ctx.getBean("helpspring");

而一般情况下都是用ClassPathXmlApplicationContext来实例化ApplicationContext容器,因为采用加载绝对路径的加载方式将导致程序灵活性差。
③WebApplicationContext 是Spring的Web应用容器,有两种方法可以在Servlet中使用。第一种方法是在Servlet的web.xml文件中配置Spring的ContextLoaderListener监听器;第二种方法同样要修改web.xml的配置文件,在配置文件中添加一个Servlet,定义使用Spring的org.springframework.web.context.Con-textL-oaderServlet类。


依赖注入的类型

…在Spring中实现IoC容器的方法是依赖注入。通常有两种实现方式,一种是使用构造方法注入,另一种是使用属性的setter方法注入。

1)使用属性的setter方法注入
//首先创建JavaBean
public class Student {
private String name;
private int member;
public void setName(String name) {
  this.name = name;
 }
public void setMember(int member) {
 this.member = member;
 }
 @Override
 public String toString() {
  return "Student [name=" + name + ", member=" + member + "]";}
}
//applicationContext.xml中的内容
<?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.xsd">
<!-- 如何配置一个bean,将指定类配置给Sprig,让spring来创建其对象的实列 -->
<bean id="helpspring" class="com.spring.ioc01.Student">
<!-- 为属性赋值 -->
 <property name="name" value="张三"></property>
 <property name="member" value="32"></property>
</bean>
</beans>
//text.java中的代码
@Test
 public void test01() {
//使用spring的配置文件来创建相应的实列来使用
//spring容器初始化,加载applicationContext.xml文件
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
//通过容器获取配置中的hellospring(id)的实列
Student hello=(Student) ctx.getBean("helpspring");
System.out.println(hello);
//赋值是在xml中。通过spring容器获取实例的对象!
 }
 
//最后的输出结果是:Student [name=张三, member=32]
2)使用构造方法注入
  //在用户JavaBean中创建构造方法
public class Student {
 private String name;
 private int member;
 private School school;
 public Student(String name, int member, School school) {
  super();
  this.name = name;
  this.member = member;
  this.school = school;
 }
 @Override
 public String toString() {
  return "Student [name=" + name + ", member=" + member + ", school=" + school + "]";
 }}
 
//school.java中的代码
public class School {
 private String name;
 public void setName(String name) {
  this.name = name;}
 @Override
 public String toString() {
  return "School [name=" + name + "]";
}}

▲constructor-arg元素(直接执行带参构造器)用于定义类构造方法的参数,index用于定义参数的位置(从0开始),ref指定某个实例的应用(指定对BeanFactory其他bean的引用关系)。如果两个或多个构造函数的参数是相同的类型,则唯一的选择是使用index特性来标识每一个< constructor-arg>元素对应的构造函数参数。

//applicationContext.xml中的内容
<?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.xsd">
<!-- 如何配置一个bean,将指定类配置给Sprig,让spring来创建其对象的实列 -->
<bean id="school" class="com.spring.ioc01.School">
 <property name="name" value="大学"></property></bean>
<bean id="helpspring" class="com.spring.ioc01.Student">
<!-- 为属性赋值 -->
<!-- value可以为构造方法传参 -->
<constructor-arg index="0" value="张三"/>
<constructor-arg index="1" value="12"/>
<constructor-arg index="2" ref="school"/>
</bean>
</beans>
 @Test
 public void test02() {
 // String name="jiayou";
 //使用spring的配置文件来创建相应的实列来使用
  //spring容器初始化,加载applicationContext.xml文件
  ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
  //通过容器获取配置中的hellospring(id)的实列
      Student hello=(Student) ctx.getBean("helpspring");
      System.out.println(hello);}}
      //赋值是在xml中。通过spring容器获取实例的对象! 
      //运行的结果:Student [name=张三, member=12]

Bean的配置

…Spring容器创建或管理的应用对象称为bean。在Spring框架的术语中,一个元素代表一个bean定义。
元素的常用属性:

属性的名称 描述
id 指定bean的唯一名称
class 指定bean的完全限定名
name 指定bean的别名,与id差不多,差别在于可以使用的字符类型不同
scope 指定Bean实例的作用域
Bean的作用域

在Bean的作用域中,singleton和prototype是最常用的两种

1)singleton作用域

…当Spring中一个bean的作用域为singleton时,那么Spring IoC容器中只会存在一个共享的该bean的实列,并且所有对该bean的引用,只要id与bean定义相匹配,则只会返回bean的单一实例。而singleton是scope的默认方式,因此有两种方式进行设置:

<bean id="helpspring" class="com.spring.ioc01.Student"></bean>

<bean id="helpspring" class="com.spring.ioc01.Student" scope="singleton"></bean>

在此作用域下,Spring能精确地知Bean何时被创建,何时初始化完成,以及何时被销毁。

2)prototype作用域

当将bean的scope设置为prototype时,Spring IoC容器将为每次请求创建一个新的实列。

<bean id="helpspring" class="com.spring.ioc01.Student" scope="prototype"></bean>

在此作用域下的bean,Spring只负责创建,当容器创建bean的实列后,容器将实例对象的生命周期的管理工作交给请求方之后,就不再拥有当前返回对象的引用,容器将实例对象的生命周期的管理工作交给请求方负责。▲对所有有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用。(这句话自己现在还没有很理解,先记录下来)

Bean的生命周期

…BeanFactory中bean的生命周期分为实例化、初始化、使用和销毁四个阶段。


Bean的实例化

Spring容器有三种方法来管理返回的对象实例。

1)构造方法实例化

Spring容器可以调用Bean对应类中的无参数构造来实例化Bean

public class BeanClass {
  public String message;
public BeanClass() {
   message="构造方法实例化";
  }
}
//在applicationcontext.xml中的内容
<?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.xsd">
<bean id="factory" class="com.spring.ioc02.BeanClass">
</bean>
</beans>
 @Test
 public void test01() {
 ///使用spring的配置文件来创建相应的实列来使用
  //spring容器初始化,加载applicationContext.xml文件
    ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
    //通过容器获取配置中的hellospring(id)的实列
     BeanClass hello=(BeanClass) ctx.getBean("factory");
        System.out.println(hello.message);
        //赋值是在xml中。通过spring容器获取实例的对象!
 }
} 
//运行的结果:构造方法实例化
2)静态工厂实例化

…在配置Bean时,class属性指定静态工厂类,同时还需要使用factory-method来指定工厂类中的静态方法(不用创建对象)

//创建一个staticfactory 类
public class staticfactory {
public static BeanClass sfactory =new BeanClass("使用静态工厂");
public static BeanClass creatfactory() {
 return sfactory; }}
 //再创建一个BeanClass类
 public class BeanClass(){
 public String message;
 public BeanClass(String message){
 this.message=message;
 }
}
<bean id="factory" class="com.spring.ioc02.staticfactory" factory-method="creatfactory"/>
//因为是使用的静态工厂进行实例化,因此不用创建对象
public void test02(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
BeanClass beanf=(BeanClass) ctx.getBean("factory");
System.out.println(beanf.message);

//运行的结果:使用静态工厂
}
3)实例工厂实例化

…使用factory-bean属性指定配置的实例工厂,同时还需要使用factory-method指定实例工厂中的实例方法

创建一个Beanfactory类
public class Beanfactory(){
public BeanClass create =new BeanClass("实例化");
public BeanClass createBeanfactory(){
return create;
}}

▲在applicationcontext.xml文件中,静态工厂与实例化工厂有很大的区别。

<?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.xsd">
<!-- 配置工厂 -->
<bean id="myfactory" class="com.spring.ioc03.Beanfactory"/>
<!-- 使用factory-bean属性指定配置工厂 ,使用factory-method属性指定使用工厂中的哪一个方法实例化bean -->
<bean id="factory" factory-bean="myfactory" factory-method="createBeanfactory"></bean>
</beans>
 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
 //▲注意这里获取配置中的id是哪一个bean中的
 BeanClass hello=(BeanClass) ctx.getBean("factory");
  System.out.println(hello.message);
  //运行结果:实例化

Bean的初始化

…在bean被实例化的过程中,容器会按照JavaBean的定义初始化bean的所有属性和依赖关系。具体初始化步骤:
(1)在bean的定义中,如果< bean>标签使用了autowire属性,Spring会对bean完成自动装配。
(2)通过get()和set()方法配置bean的属性。
(3)如果bean实现了BeanNameAware接口,容器将会调用bean的setBeanName()方法来传递Bean的ID。
(4)同样,如果bean实现BeanFactoryAware接口,容器将会调用bean的setBeanFactory()方法将容器本身注入JavaBean中。
(5)如果在容器中注册了BeanPostProcessor接口的实现类,将调用这个实现类的postProcessBeforeInitialization()方法,完成bean的预处理方法。
(6)如果bean实现了InitialzingBean接口,容器会调用JavaBean的afterPropertiesSet()方法修改JavaBean的属性
(7)在XML中配置bean时,如果用init-method属性指定了初始化方法,那么容器会执行指定的方法来设置属性。
(8)最后,容器中如果注册了BeanPostProcessor的实现类,将调用实现类的postProcessAfternitialization()方法完成bean的后期处理方法。

Bean的销毁

…当关闭容器时,容器会销毁所有bean,如果bean定制了特殊的销毁方法,容器会在销毁该bean之前调用这个方法完成资源回收等操作。
对于销毁方法的执行,有两个条件:(1)当前的Bean需要时singleton的(2)要手工关闭容器

你可能感兴趣的:(海创软件组)