Spring笔记——Spring容器:ApplicationContext

基于 Spring 的应用中,所有的对象(即bean)生存于 Spring 容器,Spring 负责创建、装配、配置并管理这些bean的整个生命周期。


图:Spring 框架的模块。核心容器包含了Beans、Core、Context、Expression Lanuage四个模块。


一、Spring 容器

Spring 容器并不是只有一个实现,而是自带了多个容器实现,可归纳为两种不同类型:bean 工厂、应用上下文。

bean工厂:由 org.springframework.beans.factory.BeanFactory接口定义;

ApplicationContext:由 org.springframework.context.ApplicationContext接口定义。

两类别关系:ApplicationContext 基于 BeanFactory 构建,并提供应用框架级别的服务,即BeanFactory是基础,ApplicationContext是一个提升。


二、BeanFactory

基础接口定义:

public interface BeanFactory {
	String FACTORY_BEAN_PREFIX = "&";
	Object getBean(String name) throws BeansException;
	<T> T getBean(String name, Class<T> requiredType) throws BeansException;
	<T> T getBean(Class<T> requiredType) throws BeansException;
	Object getBean(String name, Object... args) throws BeansException;
	boolean containsBean(String name);
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
	boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;
	String[] getAliases(String name);
}

暂时还不太理解这些方法,后面理解原理了再注释。


三、ApplicationContext

基础继承关系:

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver{...}
可见ApplicationContext是在BeanFactory基础上定义的,实际上ApplicationContext是BeanFactory的一个超全集。

该接口的说明:

/** 
 * ApplicationContext是一个为application提供配置信息的中心接口,当application运行时,它仅是可读的,但也可能重新加载,如果接口允许的  * 话。
 * ApplicationContex提供了如下功能:
 * 
 * 1、访问application的组件(即bean)的BeanFactory中的方法。继承于:org.springframework.beans.factory.ListableBeanFactory;
 * 2、以常规方式加载文件资源的能力。继承于:org.springframework.core.io.ResourceLoader;
 * 3、发布Event到注册过的listener的能力。继承于:ApplicationEventPublisher;
 * 4、解决message的能力,即支持国际化。继承于:MessageSource;
 * 从父上下文继承,在后代语境中的定义将永远优先。 这意味着,例如,一个单亲上下文可以由整个Web应用程序使用,而每个servlet都有它独立于任何其他servlet的子环境。(不明白)

 * 除了标准的org.springframework.beans.factory.BeanFactory的生命周期的能力外,ApplicationContext实现检测和调用
 * ApplicationContextAware bean 、ResourceLoaderAware bean
 * 及ApplicationEventPublisherAware、MessageSourceAware bean。
 */


所以Application 比BeanFactory多了3项能力:加载资源文件能力、发布事件能力、国际化能力。看第四点中示例!

关于Aware 接口的基础,查看另外一篇日志:


四、ApplicationContext增强能力

第三点列了ApplicationContext 增加的3项能力,现分别举基础例子。

1、资源加载:ResourceLoader接口

ResourceLoader接口定义:

public interface ResourceLoader {

	/** 从class path 路径加载时的伪资源URL: "classpath:" 。不陌生,web.xml配置中指定类路径下资源时便要加此前缀*/
	String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;

	/**返回指定path的资源*/
	Resource getResource(String location);

	/**需要直接访问ClassLoader的客户端可以这样做,即以与ResourceLoader统一的方式,而不是依赖线程上下文ClassLoader*/
	ClassLoader getClassLoader();
}
说明:

Resource 也是一个接口,定义如下:

public interface Resource extends InputStreamSource {
/**说明:InputStreamSource接口中只有一个方法:InputStream getInputStream()。可见Resource本质上是一个输入流,只是丰富了方法。*/
	boolean exists();
	boolean isReadable();
	boolean isOpen();
	URL getURL() throws IOException;
	URI getURI() throws IOException;
	File getFile() throws IOException;		//常用方法
	long contentLength() throws IOException;
	long lastModified() throws IOException;
	Resource createRelative(String relativePath) throws IOException;
	String getFilename();
	String getDescription();
}
问题:
已经可以通过ResourceLoader 返回Resource 对象得到我们需要的文件了,那ResourceLoader 中getClassLoader方法有什么作用?

答:ClassLoader是java.lang包中的类,用于JVM 加载class文件,这些class文件也是广义上的资源。在ResourceLoader 中定义方法得到此类的目的应该是application运行时并不是一下子把应用所涉及的class文件都加载,而是先加载核心的,再加载我们自己写的代码生成的类,且是用到时再加载。ClassLoader 保存了加载某个class文件时所用的位置(可能是本地,也可能是网络服务器上),所以在一个已加载的A.class文件中涉及到另一个B.class的对象时,便可以通过getClassLoader 从加载A.class的资源路径中加载B.class,之后生成对象,因为A.class与B.class在web系统中都是是位于服务器上的。简言之,两个class对应了两个java文件,A.java中使用了B.java中的类,则程序执行到A.class时,A.class从哪加载的,B.class也从那加载(或许还会自动扫描那台主机上ClassPath的所有目录,以找到B.class)。

<p> Normally, the Java virtual machine loads classes from the local file
 * system in a platform-dependent manner.  For example, on UNIX systems, the
 * virtual machine loads classes from the directory defined by the
 * <tt>CLASSPATH</tt> environment variable.
 *
 * <p> However, some classes may not originate from a file; they may originate
 * from other sources, such as the network, or they could be constructed by an
 * application.  The method {@link #defineClass(String, byte[], int, int)
 * <tt>defineClass</tt>} converts an array of bytes into an instance of class
 * <tt>Class</tt>. Instances of this newly defined class can be created using
 * {@link Class#newInstance <tt>Class.newInstance</tt>}.


ResourceLoader示例:

ApplicationContext继承了ResourceLoader接口,所以可以直接获取文件。

ApplicationContext appCtx=FileSystemXMLApplication("applicationContext.xml");
Resource reSrc=appCtx.getResource("sourceURL");
//使用Resource对象获取文件
File file=reSrc.getFile();
注: sourceURL可以是"classpath:"开头的类路径,也可是"WEB-INF/src/"开头的路径,更可以是绝对路径。


2、事件发布:ApplicationEvent类、ApplicationListener接口、ApplicationContextAware接口

步骤:

(1)、写一个事件类,继承ApplicationEvent 类。如:

class SayHello enxtends ApplicationEvent{
	public SayHello(){super();}
}
(2)、写一个ApplicationEvent 事件监听类,实现 ApplicationListener接口。如:

class SayListener implement ApplicationListener{
	public void onApplicationEvent(ApplicationEvent ev){
		if(ev instanceof SayHello){
			System.out.println("收到SayHello事件");
		}
	}
}
(3)、写一个事件发布管理类,实现ApplicationContextAware 接口。如:

public class ManagerEvent implements ApplicationContextAware{
	private ApplicationContext appCtx=null;
	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		appCtx=applicationContext;
	}
	public void publish(ApplicationEvent event){/*此处运用了控制翻转的思想,即传入ApplicationEvent的子类,因为是类的继承而非接口的实现,所以在SayHello类中并没有添加实际的方法,只是用于区分事件而已*/
		if(event!=null)
			appCtx.publisherEvent(event);
	}
}
(3)、配置Spring 容器中的bean,可通过XML 配置,如:WEB-INF/src下的myConfig.xml:省略了xml声明部门

<beans>
	<bean id="hellowEvent" class="myPackageName.SayHello"/>
	<bean id="manageEvent" class="myPackage.ManageEvent"/>
	<bean id="listerner" class="myPackage.SayListener"/>
</beans>
(4)、测试:主函数部分代码:

public static void main(String[] args){
	ApplicationContext appCtx=new FileSystemApplicationContext("WEB-INF/src/myConfig.xml");
	SayHello event=appCtx.getBean("hellowEvent");
	ManageEvent manage=appCtx.getBean("manageEvent");
	manage.publish(event);//发布事件
}

结果:


说明:

Spring 所有bean位于一个容器中,即ApplicationContext或BeanFactory中,所以所有的操作都是依赖于这个容器,容器定义后,不能重新定义,只能通过refresh方法(有待补充)。如果某个bean中本身要使用容器的某个功能,应该实现ApplicationContextAware 接口,获得ApplicationContext的句柄,对其它***Aware方法同理。


3、国际化:MessageResource接口

见另一边日志:http://blog.csdn.net/qq_19865749/article/details/70195063


五、几个常用ApplicationContext

使用Spring 的基础是通过XML等形式定义一些JavaBean,之后使用Spring 的BeanFactory 或ApplicationContext 创建并管理这些JavaBean,常用的几个ApplicationContext :

1、FileSystemXmlApplicationContext:

从文件系统下的一个或多个XML 配置文件加载上下文定义。

示例:

ApplicationContext appCtx=new FileSystemXmlApplicationContext(new String[]{"WebContent/WEB-INF/applicationContext.xml","WebContent/WEB-INF/config.xml"});//以String数组形式传入多个xml文件路径
说明:

查找路径默认为工程文件夹下,所以若XML文件不是直接处于工程文件夹下,则应把路径写上,如上面的 WebContent/WEB-INF/。也可用绝对路径。


2、ClassPathXMLApplicationContext:

从类路径下的一个或多个XML 配置文件加载上下文定义。

示例:

ApplicationContext appCtx=new ClassPathXmlApplicationContext("applicationContext.xml");
说明:

查找路径默认为src下,所以同上,若XML 文件不是直接属于src文件夹下,则应该加上路径,如:xml文件放在com.milan.pojo包下,则应为:

ApplicationContext appCtx=new ClassPathXmlApplicationContext("com/milan/pojo/applicationContext.xml");


3、XmlWebApplicationContext:

从Web 应用下的一个或多个XML 配置文件中加载上下文定义。

示例:暂时不了解。









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值