loc的实现

控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法

也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。

IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。

其实就是两种方式实现loc容器

一种是xml配置文件的方式
一种就是使用注解的方式
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

一. 配置文件的方法实现loc容器

(1). 基本步骤

第一步
创建一个MAVEN工程的javaweb项目
第二步
导入spring框架的jar包的坐标
第三步
创建spring框架的xml配置文件(注意: 名字可以随便起, 约定俗成是叫applicationContext.xml)
第四步
在applicationContext.xml中配置Bean对象

<!--这里配置UserDao接口的实现类-->
    <bean id="userDaoMysql" class="dao.daoimpl.UserDaoMysqlImpl"></bean>
    <bean id="userDaoOrale" class="dao.daoimpl.UserDaoOraleImpl"></bean>

第四步
对配置好的bean进行测试

 	@Test
    public void testUserDao(){
    
    
        /*
        * 获取UserDao接口的实现类并测试方法
        * 使用loc容器来获取*/
        //1.加载spring的配置文件来创建一个叫app的对象
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDaoMysql = (UserDao) app.getBean("userDaoMysql");
        UserDao userDaoOrale = (UserDao) app.getBean("userDaoOrale");
        userDaoMysql.getUser();
        userDaoOrale.getUser();

    }

小结: 也就是说, 有了这个loc容器之后, 创建对象是就不再是 接口 = new 具体实现类; 这种硬编码的形式了, 而是统一使用一个叫app的对象的getBean(“具体实现类的配置好的id”)这个方法来获取.
实际开发中, 当我们要换掉某一个接口具体的实现类时, 就可以去通过修改applicationContext.xml这个配置文件来轻而易举的完成, 之要不换id, 代码是可以完全不必改动的. 这样一来就实现的解耦.

(2).Bean标签的常用三个属性详解

以上这样配置Bean对象
是最简单的形式, 也就是只使用bean标签的id和class这两个属性
这种情况下, 就是使用的类中的无参构造方法, 如果没有无参构造方法, 那么将不能创建对象.

1.学习scope标签

这个标签是用来决定该bean对象的作用范围的
有5个取值

  1. singleton : 默认值, 单例的, 也就是说, 每次获取的对象地址其实是一样的
  2. prototype: 多例的, 也就是说, 每次创建都会创建一个新的对象, 地址是不一样的
  3. request: 在web环境下使用, spring创建一个Bean对象, 将对象存入request域中
  4. session: 在web环境下使用, spring创建一个Bean对象, 将对象存入session域中
  5. global session: 在web环境下, 应用在Portlet环境, 如果没有Portlet环境, 那么就相当于session.

注意: scope属性还会决定对象的创建时机, 如果是singleton, 对象将会在applicationContext.xml被加载时就创建, 也就是只创建这么么一次. 而prototype既是在每一次getBean时. 说白了, 就是类的无参构造方法被调用的时机不同. scope属性还会决定对象的销毁时机, 如果是singleton, 容器销毁才会将对象也销毁, 而prototype则是, 对象长时间不使用了, 就会被java的垃圾回收机制销毁.

2. 学习init-method和destroy-method属性

init-method属性: 值是类的初始化方法, 创建对象时, 自动执行
destroy-method: 值是类的销毁方法, 销毁对象时, 自动执行

(3).以上配置就是使用的类的无参构造方法, 那怎么样使用非无参构造方法呢

有一种叫工厂静态方法实例化
有一种叫工厂实例方法实例化

1. 工厂静态方法

第一步: 先创建一个工厂类
第二步: 在工厂类中写静态方法,

public class StaticFactory {
    
    


    /*
    * 返回UserDao接口的实现类*/
    public static UserDao getUserDaoMysql(){
    
    
        return new UserDaoMysqlImpl();
    }
    public static UserDao getUserDaoOrale(){
    
    
        return new UserDaoOraleImpl();
    }
}

第三步: 在applicationContext.xml配置文件中配置这个工厂类
第四步: 使用factory-method属性

	<!--使用工厂静态方法-->
    <!--<bean id="userDao" class="factory.StaticFactory" factory-method="getUserDaoMysql"></bean>-->
    <bean id="userDao" class="factory.StaticFactory" factory-method="getUserDaoOrale"></bean>
		ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) app.getBean("userDao");
        userDao.getUser();
这是Orale的实现方法

小结: 只要我们修改配置文件中factory-method属性的值, 就可以实现切换UserDao接口不同实现类的需求, id不变, 完全不用修改代码.

2. 工厂实例方法

这个方法和静态那种的不同就是, 这种是需要先配置好该工厂类, 有了这个工厂类的id之后, 再配置工厂类的方法, 而静态的明显是工厂类和方法在同一个bean标签中

public class DynamicFactory {
    
    

    /*
    * 返回UserDao接口的实现类对象*/
    public UserDao getUserDaoMysql(){
    
    
        return new UserDaoMysqlImpl();
    }
    public UserDao getUserDaoOrale(){
    
    
        return new UserDaoOraleImpl();
    }
}
	<!--使用工厂实例方法-->
    <bean id="factory" class="factory.DynamicFactory"></bean>
    <!--<bean id="userDao" factory-bean="factory" factory-method="getUserDaoOrale"></bean>-->
    <bean id="userDao" factory-bean="factory" factory-method="getUserDaoMysql"></bean>
		ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) app.getBean("userDao");
        userDao.getUser();
这是Mysql的实现方法

小结:

  1. 借助工厂类的方法来实例化bean对象, 这样一来可以对同一个接口, 例如UserDao, 通过写方法来return的方式, 来new出实现类, 好处就是, 这样可以使用类中所用的构造方法来new
  2. 不论是静态方法, 还是非静态的方法, 明显的是, 当我们使用一个id对应一个接口时, 我们只用修改配置文件中该id的配置信息(也就是具体对应哪个方法), 就可以切换id对应的接口的实现类, 或者是同一个实现类使用不同的构造方法

猜你喜欢

转载自blog.csdn.net/weixin_45032905/article/details/121905276