Java拾遗之Spring Ioc
标签:Spring Ioc
写在前面
框架已经使用了快半年了,一直都打算写点东西巩固巩固,但一直都没动笔的冲动。
于某日心血来着,开写。
顺序是按照本人学习的顺序来写的,主要是想通过写的过程将所有知识点再串一下,回归一下。(另:也为后人学习提供更多的教程选择)
Spring
我是打算的先从框架开始写,前面的知识,例如Java Web的Servlet、JSP部分,我的博客上已经有了,我记得是我已经将我之前学习的笔记贴在了博客中,请自行参考。
当然后面我可能会重新将这些东西整理一下,当然也只是个可能,具体视我心情而定。
至于更前面的Java语法部分,以及HTML、CSS、JavaScript等Web基础部分,这个本人暂时不打算写。相关教程请自行百度。。。
Spring框架简介
Spring是什么
介绍某个东西之前,当然先介绍它是什么。先允许我引入一段较为官方的解释:
Spring是一个开源的轻量级的应用开发框架,其目的是用于简化企业级应用程序开发,减少侵入;
Spring提供的IOC和AOP应用,可以将组件的耦合度降至最低,即解耦,便于系统日后的维护和升级;
Spring为系统提供了一个整体的解决方案,开发者可以利用它本身提供的功能外,也可以与第三方框架和技术整合应用,可以自由选择采用哪种技术进行开发。
换成人话就是:Spring是一个框架,用它可以减少代码量,降低组件之前的耦合度。
为什么要用Spring
我们都知道,在如今各类面向对象的设计思想下,各类软件的业务编写都是通过一个一个对象来实现的,而Spring的作用就是用来管理所用到的这些对象,例如创建对象和维护对象之间的关系。
容器与Bean的管理
Spring容器简介
Spring其实是通过容器的方式来管理对象的,在Spring的容器中,任何Java类和Java Bean都被当做Bean来处理,而容器正是通过管理这些bean来起到管理对象的左右的。
Spring的容器实现的Ioc(控制反转)和AOP(面向切面编程)机制,这些机制可以简化Bean对象的创建和Bean对象之间的解耦。
Spring的容器有BeanFactory和ApplicationContext两种类型
Spring容器的实例化
ApplicationContext是继承自BeanFactory接口的,拥有更多的企业方法,所以推荐使用该类型,实例化方法如下:
// 加载文件系统中的配置文件
String conf = "C:\applicationContext.xml";
ApplicationContext ac = new FileSystemXmlApplicationContext(conf);
// 加载工程下classpath的配置文件
String conf = "applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
Spring容器的使用
从本质上讲,BeanFactory和ApplicationContext仅仅只是一个维护Bean定义以及相互依赖关系的高级工厂接口。通过BeanFactory和ApplicationContext我们可以访问bean定义。
首先在容器配置文件applicationContext.xml中添加Bean定义
<bean id="标识符" class="bean类型" />
然后在创建BeanFactory和ApplicationContext容器对象后,调用getBean()方法获取Bean的实例即可
bean的实例化
通过构造器来实例化
<bean id="obj1" class="java.util.GregorianCalendar" />
<bean name="obj2" class="java.util.GregorianCalendar" />
id或name属性用于指定Bean名称, 用于从Spring中查找这个Bean对象
class用于指定Bean类型, 会自动调用无参数构造器创建对象
使用静态工厂实例化
<bean id="calendarObj2" class="java.util.Calendar" factory-method="getInstance"/>
id属性用于指定Bean名称;
class属性用于指定工厂类型;
factory-method属性用于指定工厂中创建Bean对象的方法,必须用static修饰的方法。
使用实例工厂方法实例化
<bean id="calendarObj3" class="java.util.GregorianCalendar"/>
<bean id="dateObj" factory-bean="calendarObj3" factory-method="getTime"/>
id用于指定Bean名称;
factory-bean属性用于指定工厂Bean对象;
factory-method属性用于指定工厂中创建Bean对象的方法。
Bean的命名
bean的名称
在Spring容器中,每个Bean都需要有名字(即标识符),该名字可以用 <bean>元素的id或name属性指定
id属性比name严格,要求具有唯一性,不允许用“/”等特殊字符
bean的别名
为已定义好的Bean,再增加另外一个名字引用,可以使用<alias>指定
<alias name="fromName" alias="toName"/>
Bean的作用域
Spring容器在实例化Bean时,可以创建以下作用域的Bean对象
作用域 | 描述 |
---|---|
singleton | 在每个SpringIoC容器中一个bean定义对应一个对象实例,默认项 |
prototype | 一个bean定义对应多个对象实例 |
request | 在一次HTTP请求中,一个bean定义对应一个实例,仅限于Web环境 |
session | 在一个HTTP Session中,一个bean定义对应一个实例,仅限于Web环境 |
global Session | 在一个全局的HTTP Session中,一个bean定义对应一个实例;仅在基于portlet的Web应用中才有意义,Portlet规范定义了全局Session的概念 |
上面的Bean作用域,可以通过<bean>定义的scope属性指定
Bean的生命周期回调
- 指定初始化回调方法
<bean id="exampleBean" class="com.foo.ExampleBean " init-method= " init" >
</bean>
- 指定销毁回调方法,仅适用于singleton模式的bean
<bean id="exampleBean" class="com.foo.ExampleBean" destroy-method= "destroy" >
</bean>
提示:指定销毁回调方法,仅适用于singleton模式的bean
- 在顶级的 <beans/>元素中的default-init-method属性,可以为容器所有指定初始化回调方法
<beans default-init-method ="init">
<bean id="exampleBean" class="com.foo.ExampleBean “/>
</beans>
- 在顶级的<beans/>元素中的default-destroy-method属性,可以为容器所有<bean>指定销毁回调方法
<beans default-destroy-method =“destroy">
<bean id="exampleBean" class="com.foo.ExampleBean “/>
</beans>
Bean延迟实例化
在ApplicationContext实现的默认行为就是在启动时将所有singleton bean提前进行实例化
如果不想让一个singleton bean在ApplicationContext初始化时被提前实例化,可以使用<bean>元素的lazy-init=”true”属性改变
一个延迟初始化bean将在第一次被用到时实例化
<bean id="exampleBean" lazy-init="true" class="com.foo.ExampleBean "/>
在顶级的<beans/>元素中的default-lazy-init属性,可以为容器所有<bean>指定延迟实例化特性
指定bean依赖关系
当一个bean对另一个bean存在依赖关系时,可以利用<bean>元素的depends-on属性指定
<bean id="beanOne" class="ExampleBean" depends-on="manager"/>
<bean id="manager" class="ManagerBean" />
当一个bean对多个bean存在依赖关系时,depends-on属性可以指定多个bean名,用逗号隔开
<bean id="beanOne" class="ExampleBean" depends-on="manager1, manager2"/>
容器的Ioc应用
Ioc的概念
IoC全称是Inversion of Control,被译为控制反转;
IoC是指程序中对象的获取方式发生反转,由最初的new方式创建,转变为由第三方框架创建、注入。第三方框架一般是通过配置方式指定注入哪一个具体实现,从而降低了对象之间的耦合度
IOC按实现方法不同,可以分为依赖注入DI和依赖查找两种
Spring容器是采用DI方式实现了IOC控制,IOC是Spring框架的基础和核心;
DI全称是Dependency Injection ,被译为依赖注入;
DI的基本原理就是将一起工作具有关系的对象,通过构造方法参数或方法参数传入建立关联,因此容器的工作就是创建bean时注入那些依赖关系。
IOC是一种思想,而DI是实现IOC的主要技术途径
DI主要有两种注入方式,即Setter注入和构造器注入
Setter注入
通过调用无参构造器或无参static工厂方法实例化bean之后,调用该bean的setter方法,即可实现setter方式的注入。
public class JDBCDataSource {
private String driver;
public void setDriver(String driver) {
try{//注册数据库驱动
Class.forName(driver);
this.driver = driver;
}catch(Exception e){
throw new RuntimeException(e);
}
}
//其他代码… …
}
在容器xml配置中,配置注入参数。
<bean id="dataSource" class="org.tarena.dao.JDBCDataSource">
<property name="driver" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:XE"/>
<property name="user" value="openlab"/>
<property name="pwd" value="open123"/>
</bean>
构造器注入
基于构造器的注入是通过调用带参数的构造器来实现的, 容器在bean被实例化的时候,根据参数类型执行相应的构造器。
public class OracleUserDAO implements UserDAO{
private JDBCDataSource dataSource;
public OracleUserDAO(JDBCDataSource dataSource) {
this.dataSource = dataSource;
}
//其他代码… …
}
按构造参数索引指定注入
<bean id="dataSource" class="org.tarena.dao.JDBCDataSource">
<property name="driver" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:XE"/>
<property name="user" value="openlab"/>
<property name="pwd" value="open123"/>
</bean>
<bean id="userDAO" class="org.tarena.dao.OracleUserDAO">
<constructor-arg index="0" ref="dataSource"/>
</bean>
自动装配
Spring IoC容器可以自动装配(autowire)相互协作bean之间的关联关系,autowire可以针对单个bean进行设置,autowire的方便之处在于减少xml的注入配置
在xml配置文件中,可以在<bean/>元素中使用autowire属性指定自动装配规则,一共有五种类型值
属性值 | 描述 |
---|---|
no | 禁用自动装配,默认值 |
byName | 根据属性名自动装配。此选项将检查容器并根据名字查找与属性完全一致的bean,并将其与属性自动装配 |
byType | 如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配 |
constructor | 与byType的方式类似,不同之处在于它应用于构造器参数 |
autodetect | 通过bean类来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式 |
配置实例
<bean id="userDAO" class="org.tarena.dao.OracleUserDAO">
<constructor-arg index="0" ref="dataSource"/>
</bean>
<bean id="userService" class="org.tarena.service.UserService" autowire="byType"/>
上述配置,在UserService中如果存在接收UserDao类型的方法Setter方法,Spring就可以自动将userDAO对象注入进去