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

Hedva ·
更新时间:2024-11-14
· 655 次阅读

目录 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中的内容 //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特性来标识每一个元素对应的构造函数参数。

//applicationContext.xml中的内容 @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的默认方式,因此有两种方式进行设置:

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

2)prototype作用域

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

在此作用域下的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中的内容 @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; } } //因为是使用的静态工厂进行实例化,因此不用创建对象 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文件中,静态工厂与实例化工厂有很大的区别。

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的定义中,如果标签使用了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)要手工关闭容器


作者:丫。丫



spring ioc 软件

需要 登录 后方可回复, 如果你还没有账号请 注册新账号