栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

自学Spring框架之 IoC

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

自学Spring框架之 IoC

 IoC(Inversion of Control)控制反转

                    对象的创建控制权由程序内部转移到外部,这种思想称为控制反转.

简单来说就是在程序中使用对象时,不使用new 产生对象,而由外部提供对象.

Spring 就提供了一个容器,称为IoC容器 ,该容易可以为程序内部提供对象,实现解耦

IoC容器负责对象的创建,初始化等工作,被创建或被管理的对象在Ioc容器中统称为bean

 解释:bean可以看成一个'变量',这个'变量'的类型是一个对象,在Spring配置文件中配置bean的具体类型属性

思考:如果一个类的内部需要另一个类对象时,需要配置几个bean?这俩个bean什么关系?

IoC提供了一种解决方法 DI(dependcy Injection)依赖注入

具体意思就是把两个bean 之间建立依赖关系,称为依赖注入

注意并不是随意绑定的,绑定bean关系的前提是在程序内部一个类中需要使用另一个类的对象时,就把这两个类分别配置一个bean,然后对这两个bean进行绑定

IoC入门案例

     分析:IoC是管理类对象的,IoC容器中可以由许多的bean,通过配置文件将被管理对象告知IoC容器,再通过接口以及接口方法获取IoC容器和bean

1.在pom.xml配置文件中添加Spring坐标 

    
      org.springframework
      spring-context
      5.2.10.RELEASE
    

 导入坐标后右键resources -->new  --> xml Configuration File --> Spring Config

创建一个Spring配置文件,起名最好是  applicationContext  

2.配置bean 

在applicationContext配置文件中使用标签来配置bean,格式如下

 其中bean标签可以是自闭和标签也可以是围堵标签

* id属性表示给bean起的名字,这个值唯一,且可以使用name属性起别名 

* class 属性表示给bean定义的而类型,它是一个url 需要配置bean 的类的路径

例子

 这样一个类型为Person的bean就配置好了

3.获取IoC容器

public class BeanTest{
    public static void main(String args[]) throws Exception{
//ApplicationContext是一个接口,通过其实现类ClassPathXmlApplicationContext得到一个IoC容器
//通过传入配置applicationContext.xml文件让这个IoC容器中有bean
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    }
}

4.获取bean

public class BeanTest{
    public static void main(String args[]) throws Exception{
//ApplicationContext是一个接口,通过其实现类ClassPathXmlApplicationContext得到一个IoC容器
//通过传入配置applicationContext.xml文件让这个IoC容器中有bean
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//上一步中创建了一个IoC容器对象ctx 通过调用getBean()方法以及IoC中管理的bean Id值生成一个Person对象p
        Person p = ctx.getBean("person",Person.class);
        p.say();
    }
}

DI入门案例思路

分析下列代码:

代码1

public class Person {//一个Person类 里面有一个son成员和一个say方法
prviate son ;
public void say(){
System.out.println(" Person...")
son.say();
}
}

代码2

public class Son {//一个son类 里面有一个say方法
public void say(){
System.out.println(" Son...")
}
}

问题,从IoC入门案例中配置文件中只配置了Person的一个bean,但是通过IoC容器获取到属性为Person的对象后调用say方法,Person中的say方法会使用Son对象去调用Son的say方法,但是Son的对象并没有初始化所以会报异常,所以代码1优化一下就是

代码3

public class Person {//一个Person类 里面有一个son成员和一个say方法
prviate son ;
public void say(){
System.out.println(" Person...")
son.say();
}
//新增一个set方法对son进行初始化
public void setSon(Son son){
this.son =son;
}
}

最后去applicationContext 配置文件里添加一个Son类型的bean

 此时IoC容器里的两个bean并没有绑定,所以要在配置文件中绑定关系,分析出是Person类型的bean依赖Son类型的bean所以要在person中添加

 使用标签来绑定两个bean之间的关系

*name 属性代表的是Person类中的私有son成员的名称

*ref 属性代表的是IoC容器中已经配置的类型为Son类型的bean id值

bean详解

Spring容器中的Bean

对于开发者来说,开发者使用Spring框架主要是做两件事:①开发Bean;②配置Bean。对于Spring框架来说,它要做的就是根据配置文件来创建Bean实例,并调用Bean实例的方法完成"依赖注入"——这就是所谓IoC的本质。

容器中Bean的作用域

当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。Spring支持如下五种作用域:

  1. singleton: 单例模式,在整个Spring IoC容器中,singleton作用域的Bean将只生成一个实例。
  2. prototype: 每次通过容器的getBean()方法获取prototype作用域的Bean时,都将产生一个新的Bean实例。
  3. request: 对于一次HTTP请求,request作用域的Bean将只生成一个实例,这意味着,在同一次HTTP请求内,程序每次请求该Bean,得到的总是同一个实例。只有在Web应用中使用Spring时,该作用域才真正有效。
  4. session:该作用域将 bean 的定义限制为 HTTP 会话。 只在web-aware Spring ApplicationContext的上下文中有效。
  5. global session: 每个全局的HTTP Session对应一个Bean实例。在典型的情况下,仅在使用portlet context的时候有效,同样只在Web应用中有效。

如果不指定Bean的作用域,Spring默认使用singleton作用域。prototype作用域的Bean的创建、销毁代价比较大。而singleton作用域的Bean实例一旦创建成果,就可以重复使用。因此,应该尽量避免将Bean设置成prototype作用域。

创建Bean的3种方式

一.使用构造器创建Bean实例

使用构造器来创建Bean实例是最常见的情况,如果不采用构造注入,Spring底层会调用Bean类的无参数构造器来创建实例,因此要求该Bean类提供无参数的构造器。

采用默认的构造器创建Bean实例,Spring对Bean实例的所有属性执行默认初始化,即所有的基本类型的值初始化为0或false;所有的引用类型的值初始化为null

例子如下

例子

二.使用静态工厂方法创建Bean

使用静态工厂方法创建Bean实例时,class属性也必须指定,但此时class属性并不是指定Bean实例的实现类,而是静态工厂类,Spring通过该属性知道由哪个工厂类来创建Bean实例。

除此之外,还需要使用factory-method属性来指定静态工厂方法,Spring将调用静态工厂方法返回一个Bean实例,一旦获得了指定Bean实例,Spring后面的处理步骤与采用普通方法创建Bean实例完全一样。如果静态工厂方法需要参数,则使用元素指定静态工厂方法的参数。

例如有一个工厂类

public class PersonFactory {
    public static person getPerson(){
        return new Person();
    }
}

那么想要通过静态工厂方法创建Bean实例,配置bean时这样写


三.调用实例工厂方法创建Bean

实例工厂方法与静态工厂方法只有一个不同:调用静态工厂方法只需使用工厂类即可,而调用实例工厂方法则需要工厂实例。使用实例工厂方法时,配置Bean实例的元素无须class属性,配置实例工厂方法使用factory-bean指定工厂实例。
采用实例工厂方法创建Bean的元素时需要指定如下两个属性:

  • factory-bean: 该属性的值为工厂Bean的id。
  • factory-method: 该属性指定实例工厂的工厂方法。

若调用实例工厂方法时需要传入参数,则使用元素确定参数值。

例子如下

有一个实例工厂

//实例工厂创建对象
public class PersonFactory {
    public UserDao getPerson(){
        return new Person();
    }
}

那么配置person的bean时要先配置实例工厂的bean然后通过工厂bean来创建person的bean

代码如下



    

解析,大概意思就是,一个创建Person对象的工厂类PersonFactory ,是实例工厂,所以想要调用其方法时必须是这个工厂类的实例对象.方法,这种形式去调用,所以在配置Person时需要先创建一个PersonFactory类型的bean,得到工厂类的对象,然后在配置Person时,加上工厂对象和工厂方法创建一个Person的bean 

发现问题:可以看出这种方式存在很大的问题,一是PFactory这个bean 没有什么意义,就是为了创建Person而配置的,其次就是factory-method 中的方法名是硬编程,所以就有了改良版的调用实例工厂方法创建bean

三.改良版的调用实例工厂方法创建bean

代码如下

//此工厂类继承了接口 FactoryBean后面泛型是想要创造的bean类型
public class PersonFactoryBean implements FactoryBean {
    //代替原始实例工厂中创建对象的方法
    public Person getObject() throws Exception {
        return new Person();
    }

    public Class getObjectType() {
        return Person.class;
    }
    public boolean isSingleton() {
        return true;//创建对象为单例的 false 是非单例
    }

}

bean的配置就可以简化一下,代码如下

 这个是重点

bean的生命周期

在类中定义初始化和销毁方法init和destroy方法,然后在配置bean时,使用属性init-method 和destroy-method 并把类中定义的初始化方法和销毁方法传入

代码如下

public class Person {//一个Person类 里面有init方法和destroy方法

public void init(){
System.out.println("初始化方法被调用");
}
public void destroy(){
System.out.println("销毁方法被调用");
}
}

 在配置bean如下

 bean的生命周期和Ioc容器有关系,加入Java 虚拟机在获取IoC容器后,主程序内没有close.ctx虚拟机会直接关掉,所以Ioc容器中的bean还没来得及执行销毁方法就没了

但是上述代码还可以再优化一下如下

class Person implements InitializingBean, DisposableBean {

    public void say(){
        System.out.println("Person say方法....");
    }
    //重写这两个方法
    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet方法...");
    }

    public void destroy() throws Exception {
        System.out.println("destroy方法.....");
    }
}

配置Person类型的bean时就正常的给id值和class路径

 在获取Ioc容器后直接获取Person类型的bean

        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = ctx.getBean("person", Person.class);
        person.say();
        ctx.close();

 可以看出,只要继承了InitializingBean, DisposableBean这个两个接口并且重写afterPropertiesSet和destroy方法,在获取对应bean时就会自动执行这两个方法。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/998672.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号