【软件开发架构平台】CH2 Spring IoC和Bean管理

IoC

控制反转:是面向对象编程中的一种设计原则,可以用来降低计算机代码之间的耦合度

控制反转常用的实现方式是依赖注入DI

通过控制反转,对象在被创建的时候,由系统的外部实体,将其所依赖的对象的引用传递(注入)进来,而不是系统内部进行对象的创建

具体实现:Spring Framework

以HelloWord程序为例

在面向对象的思想(OOP)的指导下,可将程序分为三个模块:

  • 从持久化数据(文件、数据库等)中读取字符串
  • 对读取的数据进行处理(编码、格式等)
  • 将数据展现在用户界面(命令行、GUI、HTML等)

针对上述三个功能可写出三个类:

  • FileHelloStr类:从持久化数据中读取信息
  • HelloWorld类:业务逻辑,如添加Software后缀
  • HelloWorldClient:将信息输出到命令行

存在的问题:

  • HelloWorld类依赖于FileHelloWord类
  • HelloWorldClient类依赖于HelloWorld类
  • 系统的各部分之间相互依赖,导致可维护性和可扩展性差,不适合大型、企业级软件开发

解决方案:

  • 面向接口的编程思想,将业务逻辑层(HelloWorld)和DAO层(FileHelloStr)的耦合消除
  • 业务逻辑针对接口操作,对具体的DAO类的操作,委托给外部类

工厂模式分析:

  • 业务逻辑、数据访问和界面逻辑三者之间完全解耦
  • 工厂类负责创建和集成应用所需的各类对象
  • 借助依赖注入(DI)和工厂模式实现了控制反转(IoC)
IoC原理总结
  • 用于降低耦合度,实现方式为依赖注入
  • 由系统外部实体将依赖的对象注入进来(不用new)
  • 调用方引用一个接口或类就可以获得对象

IoC核心思想:解耦合,将组件的构建和组件的使用分开,实现每个组件时只考虑组件内部的事情,要点是明确和定义组件间的接口

IoC实现基础:面向接口编程 + 工厂模式 + 依赖注入

依赖注入

构造注入

<constructor-arg>
<bean name="对象名" class="类从哪创建">
	<constructor-arg>
		<ref bean="fileHello">
	</constructor-arg>	
</bean>

设值注入

<property>
<bean id="userBiz" class="UserBizImpl">
	<property name="userDAO" ref="userDAO"/>
</bean>

区别

  • 设值注入支持大部分依赖注入,构造注入不支持
  • 设值注入不会重写构造方法的值
  • 设值注入不能保证某种依赖是否已经被注入,构造注入不允许生成依赖关系不完整的对象
  • 设值注入使DAO,Impl,Service,ServiceImpl,配置applicationContext.xml实现
    构造注入使用ServiceImpl,配置applicationContext.xml实现
Spring IoC

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中填类名)
 //如果有参需要使用<constructor-arg>
<bean id="exampleBean" class="examples.ExampleBean"/>
//...............................................................
//静态工厂
//在class助兴中填静态工厂类名,factory-method属性中填方法名
<bean id="clientService" class="examples.ClientService" factory-method="createInstance"/>
//
public class ClientService{
	private static ClientService clientService=new ClientService();
	private ClientService(){}
	
	public static ClientService createInstance(){
		//1.私有(别人不可用)
		//2.对外获取方法需为静态(可以直接使用类名调用方法)
		return clientService;
	}
}
//...............................................................
//实例工厂
//先定义工厂bean,再设定factory-method和factory-bean属性
<bean id="serviceLocator" class="examples.DefaultServiceLocator" >
</bean>
<bean id="clientService" factory-bean="serviceLocator" factory-method="createClientServiceInstance"/>
//
public class DefaultServiceLocator(){
	private static ClientService clientService=new ClientServiceImpl();
	private DefaultServiceLocator(){}
	public ClientService createClientServiceInstance(){
		return clientService;
	}
}
     

Bean的生命周期

实例化、属性赋值、初始化、销毁

bean的依赖注入:构造注入/设值注入

//构造注入
<beans>
	<bean id="Foo" class="x.y.Foo">
		//Foo下有两个属性
		<constructor-arg ref="bar"/>
		<constructor-arg ref="baz"/>
	</bean>
	<bean id="bar" class="x.y.Bar">
	<bean id="baz" class="x.y.Baz">
</beans>
//
package x,y;
public class Foo{
	public Foo(Bar bar,Baz baz){
		//...
	}
}
        
//...............................................................
//设值注入
<bean id="exampleBean" class="examples.ExampleBean">
	<property name="beanOne"><ref bean="anotherExampleBean"/>
	<property name="beanTwo"><ref bean="yetAnotherBean"/>
	<property name="integerProperty" value="1">
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean">
<bean id="yetAnotherBean" class="examples.YetAnotherBean">
//
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类似
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值