控制反转:是面向对象编程中的一种设计原则,可以用来降低计算机代码之间的耦合度
控制反转常用的实现方式是依赖注入DI
通过控制反转,对象在被创建的时候,由系统的外部实体,将其所依赖的对象的引用传递(注入)进来,而不是系统内部进行对象的创建
具体实现:Spring Framework
以HelloWord程序为例
在面向对象的思想(OOP)的指导下,可将程序分为三个模块:
- 从持久化数据(文件、数据库等)中读取字符串
- 对读取的数据进行处理(编码、格式等)
- 将数据展现在用户界面(命令行、GUI、HTML等)
针对上述三个功能可写出三个类:
- FileHelloStr类:从持久化数据中读取信息
- HelloWorld类:业务逻辑,如添加Software后缀
- HelloWorldClient:将信息输出到命令行
存在的问题:
- HelloWorld类依赖于FileHelloWord类
- HelloWorldClient类依赖于HelloWorld类
- 系统的各部分之间相互依赖,导致可维护性和可扩展性差,不适合大型、企业级软件开发
解决方案:
- 面向接口的编程思想,将业务逻辑层(HelloWorld)和DAO层(FileHelloStr)的耦合消除
- 业务逻辑针对接口操作,对具体的DAO类的操作,委托给外部类
工厂模式分析:
- 业务逻辑、数据访问和界面逻辑三者之间完全解耦
- 工厂类负责创建和集成应用所需的各类对象
- 借助依赖注入(DI)和工厂模式实现了控制反转(IoC)
- 用于降低耦合度,实现方式为依赖注入
- 由系统外部实体将依赖的对象注入进来(不用new)
- 调用方引用一个接口或类就可以获得对象
IoC核心思想:解耦合,将组件的构建和组件的使用分开,实现每个组件时只考虑组件内部的事情,要点是明确和定义组件间的接口
IoC实现基础:面向接口编程 + 工厂模式 + 依赖注入
依赖注入
构造注入
设值注入
区别
- 设值注入支持大部分依赖注入,构造注入不支持
- 设值注入不会重写构造方法的值
- 设值注入不能保证某种依赖是否已经被注入,构造注入不允许生成依赖关系不完整的对象
- 设值注入使DAO,Impl,Service,ServiceImpl,配置applicationContext.xml实现
构造注入使用ServiceImpl,配置applicationContext.xml实现
Spring IoC中最核心的组件时工厂类
- Spring创建时通过Bean工厂来实现控制反转和依赖注入的,从而达到管理任意类型的应用对象的目的
- Bean工厂使用统一的方式装配所有的应用对象,时实例化、配置和管理Bean的容器,是Spring其他组件服务的基础
- Spring框架中,最基本的Bean工厂是接口BeanFactory
- ApplicationContext构建在BeanFactory基础之上。除了具有BeanFactory的功能之外,还添加了大量的功能,如Spring IoC集成、国际化资源、事件机制。
FileSystemXmlApplicationContext:可将配置文件放在项目的任何地方,但需要告知
ClassPathXmlApplicationContext:将配置文件放在项目的根目录下
Spring Bean管理- 由Ioc容器初始化,装配,管理的类
- Spring框架是实例化,配置,管理Bean的容器,通过Bean工厂实现Ioc和DI
- 管理分为xml和注解
Bean的基本配置
- Id和name
-
- 一般而言,通过id属性指明Bean的实例名
- id属性在整个IoC容器中必须唯一
- 如果Bean的名称中含有特殊字符,就是用name属性进行设置
- class
-
- class属性用于设置一个类的完整路径名
Bean管理——xml方式
作用域:
- singleton:Bean以单实例的方式存在,即在Spring IoC容器中只存在一个实例
- prototype:每次调用getBean()时都会返回一个新的实例
- request:仅适用Web环境。每次Http请求都会创建一个新的Bean
- session:仅适用Web环境。作用域等同HTTP session的效用
三种实例化方式:类构造器(默认无参构造方法)/静态工厂(简单工厂模式)/实例工厂(工厂方法模式)
//Bean的实例化 //............................................................... //类构造器(class中填类名) //如果有参需要使用//............................................................... //静态工厂 //在class助兴中填静态工厂类名,factory-method属性中填方法名 // public class ClientService{ private static ClientService clientService=new ClientService(); private ClientService(){} public static ClientService createInstance(){ //1.私有(别人不可用) //2.对外获取方法需为静态(可以直接使用类名调用方法) return clientService; } } //............................................................... //实例工厂 //先定义工厂bean,再设定factory-method和factory-bean属性 // public class DefaultServiceLocator(){ private static ClientService clientService=new ClientServiceImpl(); private DefaultServiceLocator(){} public ClientService createClientServiceInstance(){ return clientService; } }
Bean的生命周期
实例化、属性赋值、初始化、销毁
bean的依赖注入:构造注入/设值注入
//构造注入// package x,y; public class Foo{ public Foo(Bar bar,Baz baz){ //... } } //............................................................... //设值注入 //Foo下有两个属性 // public class ExampleBean(){ private AnotherBean beanOne; private YetAnotherBean beanTwo; private int i; public void setBeanOne(AnotherBean beanOne){ this.beanOne=beanOne; } public void setBeanTwo(YetAnotherBean beanTwo){ this.beanTwo=beanTwo; } public void setintegerProperty(int i){ this.i=i; } }
其他注入方式:
- 复杂数据类型注入:List、Set、Map
- p名称空间方式:p:<属性名>
- SpELl表达式语言:#{表达式}
Bean管理——注解方式
- @Component:用于一般意义的Bean注解
- @Repository:用于对DAO实现类的注解
- @Service:用于对Service业务逻辑类的注解
- @Controller:用于对Controller控制器的注解
- @Autowired:实现属性的自动注入
-
- @Autowired注解默认按类型进行自动注入,类型相同时则按照名称进行注入
- @Autowired注解的required属性用来指定一定要找到匹配的Bean
- @Resource:与@Autowired类似



