什么是控制反转
什么是依赖注入
BeanFactory
ApplicationContext
Bean的scope
Bean的生命周期
Type2 Ioc、Type3 IoC
集合对象
资源、消息、事件
什么是控制反转?
IoC,用白话来讲,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:控制权由应用代码中转到了外部容器,控制权的转移,是所谓的反转。
什么是依赖注入?
相对IoC 而言,“依赖注入”的确更加准确的描述了这种设计理念。从名字上理解,所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。
依赖注入的几种实现类型
Type1 IoC(接口注入)
Type2 IoC(设值注入)
Type3 IoC(构造注入)
BeanFactory
BeanFactory负责读取Bean定义文件;管理对象的加载、生成;维护Bean对象与Bean对象之间的依赖关系;负责Bean的生命周期。BeanFactory接口包括了5种方法可以调用:
boolean containsBean(String name)
是否包含指定名称的Bean
Object getBean(String name)
取得相对应的Bean实例
Object getBean(String name,Class requiredType)
取得相对应的Bean实例,并转换到指定的类
Class getType(String name)
取得相对应的Bean的Class实例
boolean isSingleton(String name)
测试指定的Bean之scope是否为Singleton
ApplicationContext
ApplicationContext提供一个应用程序所需的更完整的框架功能,例如:
提供更方便地取得资源文件的方法
提供解析文字消息的方法
支持国际化消息
可以发布事件,对事件感兴趣的Bean可以接收这些事件
在实现ApplicationContext的类中,最常使用的是以下3个:
FileSystemXmlApplicationContext
可指定XML定义文件的相对路径或绝对路径读取定义文件
ClassPathXmlApplicationContext
从Classpath设置路径中读取XML定义文件
XmlWebApplicationContext
在Web应用程序的文件架构中,指定相对位置读取定义文件
举例:
可以将第一个Spring程序中的SpringDemo类修改为以下内容:
package org.fire;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringDemo {
public static void main(String[] args) {
ApplicationContext context=new
ClassPathXmlApplicationContext("beans-config.xml");
HelloBean hello=(HelloBean) context.getBean("helloBean");
System.out.println(hello.getHelloWorld());
}
}
Bean的scope
在Spring中,从BeanFactory或ApplicationContext取得的实例被默认为Singleton,也就是默认每一个Bean名称只维持一个实例。
使用Singleton模式产生单一实例,对单线程的程序来说不会有什么问题,但对于多线程的程序,必须注意到线程安全的问题,防止多个线程同时存取共用资源所引发的数据不同步问题,通常Singleton的Bean都是无状态的。
在Spring中,“scope”属性预设是“singleton”,通过将其设置为“prototype”,使得每次指定名称来取得Bean时,都会产生一个新的实例。
举例:
<bean id="date" class="java.util.Date" scope="singleton" />
Resource rs = new ClassPathResource("beans-config1.xml");
BeanFactory factory = new XmlBeanFactory(rs);
Date d1 = (Date) factory.getBean("date");
Thread.sleep(1000);
Date d2 = (Date) factory.getBean("date");
System.out.println(d1);
System.out.println(d2);
<bean id="date" class="java.util.Date" scope="prototype" />
Resource rs = new ClassPathResource("beans-config2.xml");
BeanFactory factory = new XmlBeanFactory(rs);
Date d1 = (Date) factory.getBean("date");
Thread.sleep(1000);
Date d2 = (Date) factory.getBean("date");
System.out.println(d1);
System.out.println(d2);
Bean的生命周期
一个Bean从建立到销毁,会历经几个执行阶段,我们可以在Bean的配置文件中定义“init-method”属性来设置初始化方法;定义“destroy-method”属性来设置销毁方法。
<bean id="beanLife“
class="BeanLife"
lazy-init="true"
init-method="init"
destroy-method="destroy">
</bean>
public class BeanLife {
public void init(){
System.out.println("init");
}
public void destroy(){
System.out.println("destroy");
}
public static void main(String[] args) {
AbstractApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
BeanLife life=(BeanLife) context.getBean("beanLife");
//向JVM注册关闭
context.registerShutdownHook();
}
}
Type2 Ioc、Type3 IoC
在Spring中两种基本的依赖注入方式是设值注入及构造注入。在第1章完成的第一个Spring程序中,利用了Bean的Setter方法完成依赖注入。下面来介绍构造注入如何实现。
实现步骤:
JavaBean
import java.util.Date;
public class HelloBean {
private String helloWorld;
private Date date;
public HelloBean(String helloWorld, Date date) {
this.helloWorld = helloWorld;
this.date = date;
}
……
}
Bean的配置文件
<bean id="date" class="java.util.Date" />
<bean id="helloBean" class="HelloBean">
<constructor-arg index="0">
<value>Hello,fire</value>
</constructor-arg>
<constructor-arg index="1">
<ref bean="date" />
</constructor-arg>
</bean>
示范程序
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringDemo {
public static void main(String[] args) {
ApplicationContext context=new
ClassPathXmlApplicationContext("applicationContext.xml");
HelloBean hello=(HelloBean) context.getBean("helloBean");
System.out.println(hello.getHelloWorld());
System.out.println(hello.getDate());
}
}
集合对象
对于Array、List 、Set 、Map等集合对象,在注入前必须填充入一些对象至集合中,然后再将集合注入至所需的Bean,也可以交由Spring的IoC容器来自动维护或生成集合对象,并完成依赖注入。
实现步骤:
JavaBean
import java.util.List;
import java.util.Map;
public class SomeBean {
private String[] someArray;
private List someList;
private Map someMap;
……
}
Bean的配置文件
<bean id="someBean" class="SomeBean">
<property name="someArray">
<list>
<value>1</value><value>2</value><value>3</value>
</list>
</property>
<property name="someList">
<list>
<value>张三</value><value>李四</value><value>五王</value>
</list>
</property>
<property name="someMap">
<map>
<entry key="1"><value>路人甲</value></entry>
<entry key="2"><value>路人乙</value></entry>
</map>
</property>
</bean>
示范程序
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
SomeBean some = (SomeBean) context.getBean("someBean");
// 取得Array类型依赖注入对象
String[] strs = some.getSomeArray();
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);
}
// 取得List类型依赖注入对象
List list=some.getSomeList();
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
// 取得Map类型依赖注入对象
Map map=some.getSomeMap();
System.out.println(map.get("1"));
System.out.println(map.get("2"));
资源、消息、事件
资源的取得
ApplicationContext.getResource()方法提供了对资源文件访问的支持,示例如下:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//获得资源对象
Resource rs = context.getResource("classpath:test.txt");
// Resource rs = context.getResource("file:src/test.txt");
//资源文件是否存在
if (rs.exists()) {
//输出资源文件的绝对路径
System.out.println(rs.getFile().getAbsolutePath());
//获得资源文件的输入流对象
InputStream in=rs.getInputStream();
InputStreamReader inr=new InputStreamReader(in);
while(inr.ready()){
System.out.print((char)inr.read());
}
in.close();inr.close();
}
解析文字消息
ApplicationContext继承了MessageSource接口,可以使用getMessage()的各种版本的方法来取得文字消息的资源文件,从而实现国际化消息的目的。
messages_en.properties
User {0} login at {1}
messages_zh.properties
用户 {0} 于 {1} 登录
<!-- 使用ResourceBundleMessageSource来取国际化消息 -->
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<!-- 设置消息资源的前置档案文件名称 -->
<property name="basename" value="messages"></property>
</bean>
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 消息中需要传递的参数
Object[] arg = { "Fire", new Date() };
// 输出英文消息
System.out.println(context.getMessage("userLogin", arg, Locale.US));
// 输出中文消息
System.out.println(context.getMessage("userLogin", arg, Locale.CHINA));
事件传播
如果打算发布事件通知ApplicationListener的实例,可以使用ApplicationContext的publishEvent()方法。示例如下:
//自定义动作事件
public class ActionEvent extends ApplicationEvent {
public ActionEvent(Object source) {
super(source);
}
}
<bean id="listener" class="ActionListener" />
//自定义动作事件监听器
public class ActionListener implements ApplicationListener{
public void onApplicationEvent(ApplicationEvent event) {
if(event instanceof ActionEvent){
System.out.println(event.getSource());
}
}
}
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
context.publishEvent(new ActionEvent("Hello"));
Spring IOC
最新推荐文章于 2024-09-11 13:58:59 发布