BeanFactory和ApplicationContext 是使用过Spring的同学耳熟能详的两个接口,其中BeanFactory是Spring框架最核心的接口,之前学习Spring开发的时候接触多的是ApplicationContext 这个面向应用的功能,当然要搭建Spring环境也可以不用了解BeanFactory这个接口,简而言之:
BeanFactor:y提供了高级的IoC的配置机制,管理不同类型的Java对象,是Spring框架的基础设施,面向的是Spring本身。
ApplicationContext:是建立在BeanFactory基础之上的,它提供了更多的面向应用的功能,诸如国际化支持,框架事件体系,易于创建实际应用,面向使用Spring的开发者。
这里先说说Spring里面的Resource接口:
Resource:为应用提供了强大的访问底层资源,下面UML列出了它的主要接口和鸡翅根体系:
这三个是常用的,这三个子类可以见名知意了,还有如:
InputStreamResource:对应的是InputStream的资源。
ServletContxtResource:负责Web应用根目录的路径加载资源,支持URL的方式访问,可以直接从jar包中访问资源。
UrlResource:可以访问任何可以通过URL表示的资源,如HTTP资源,FTP资源。
FileSystemResource:
01.
public
class
FileSourceDemo {
02.
03.
public
static
void
main(String[] args) {
04.
05.
String filePath =
"E:\\Workspace_64bit\\Myeclipses_spring3.x\\spring3_learning\\WebRoot\\WEB-INF\\spring3-servlet.xml"
;
06.
Resource res1 =
new
FileSystemResource(filePath);
07.
Resource res2 =
new
ClassPathResource(
"WEB-INF\\spring3-servlet.xml"
);
08.
// Resource res3 = new ServletContextResource(servletContext, "")
09.
System.out.println(res1.getFilename());
10.
try
{
11.
System.out.println(res1.getURL());
12.
System.out.println(res1.getFile());
13.
System.out.println(res2.getFilename());
14.
}
catch
(IOException e) {
15.
e.printStackTrace();
16.
}
17.
}
18.
}
@上面分别以系统文件路径和类路径读取本地资源文件,常用的是ClassPathResource,这样在工程移植的时候就不会出现路径问题。
SerlvetContextResource:
01.
<%@ page language="java" contentType="text/html; charset=utf-8"
02.
pageEncoding="utf-8"%>
03.
<
jsp:directive.page
import
=
"org.springframework.web.context.support.ServletContextResource"
/>
04.
<
jsp:directive.page
import
=
"org.springframework.core.io.Resource"
/>
05.
<
jsp:directive.page
import
=
"org.springframework.web.util.WebUtils"
/>
06.
<%
07.
Resource res = new ServletContextResource(application,"/WEB-INF/classes/conf/testFile.txt");
08.
out.print(res.getFilename()+"<
br
/>");
09.
out.print(WebUtils.getTempDir(application).getAbsolutePath());
10.
%>
testFile.txt
A:\Program Files (x86)\Apache Software Foundation\Tomcat 6.0\work\Catalina\localhost\spring3_chapter3
资源加载路径表示:
常用的classpath(值加载第一个包下的资源文件):,classpath*(加载类路径下多个模块多个相同报名的资源文件):
在实际开发中常用的就是classpath路径下加载资源文件了,那么Spring提供了一个强大的资源加载机制,在通过classpath:和file:标示符加载多个资源文件大小的同时,提供了Ant风格:
? :匹配文件名中的一个字符。
* :匹配文件名中的任意字符。
** :匹配多层路径。
要使用这些Ant风格的方式,就要用到了资源加载器,ResourceLoader:
看一个小实例:
01.
public
class
ResourceUtilsDemo {
02.
public
static
void
main(String[] args) {
03.
ResourcePatternResolver resolver =
new
PathMatchingResourcePatternResolver();
04.
try
{
05.
//Ant风格
06.
// Resource[] resources = resolver
07.
// .getResources("classpath*:/*.xml");
08.
// Resource[] resources = resolver
09.
// .getResources("classpath*:com/**/*.xml");
10.
//Ant只有在调用getResources方法返回多个资源文件的时候使用
11.
Resource[] resources = resolver
12.
.getResources(
"classpath*:/?eans.xml"
);
13.
for
(Resource resource : resources) {
14.
System.out.println(resource.getFilename());
15.
}
16.
}
catch
(IOException e) {
17.
e.printStackTrace();
18.
}
19.
}
20.
}
看看BeanFactory的体系结构:
@BeanFactory:提供了getBean,也就是我们常用的
@HierachicalBeanFactory:可以查看Bean的个数,获取Bean的配置名,查看容器是否包某一Bean
@ConfigurableBeanFactory:增强了IoC容器的可定制性,定义了设置类装载器,属性编辑器,容器初始化后置处理器等。
@AutowireCapableBeanFactory:定义了将容器中的Bean按某种规则进行自动装配的方法
@SingletonBeanRegistry:定义了允许在运行期想容器注册单实例Bean的方法。
@BeanDefinitionRegistry:Spring配置文件中的<bean>节点是通过BeanDefinition对象表示,BeanDefinition描述了Bean的配置信息,BeanDefinitionRegistry提供了向容器手工注册BeanDefinition对象的方法。
BeanFactory的应用,看一个小实例:
src目录下,beans.xml:
01.
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
02.
<
beans
xmlns
=
"http://www.springframework.org/schema/beans"
03.
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:p
=
"http://www.springframework.org/schema/p"
04.
xsi:schemaLocation="http://www.springframework.org/schema/beans
05.
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
06.
<
bean
id
=
"car"
class
=
"com.baobaotao.Car"
07.
init-method
=
"myInit"
08.
destroy-method
=
"myDestory"
09.
p:brand
=
"红旗CA72"
10.
p:maxSpeed
=
"200"
11.
/>
12.
</
beans
>
01.
public
class
BeanFactoryDemo {
02.
public
static
void
main(String[] args)
throws
Throwable{
03.
ResourcePatternResolver resolver =
new
PathMatchingResourcePatternResolver();
04.
Resource res = resolver.getResource(
"classpath:beans.xml"
);
05.
System.out.println(res.getURL());
06.
BeanFactory bf =
new
XmlBeanFactory(res);
07.
System.out.println(
"init BeanFactory."
);
08.
09.
Car car = bf.getBean(
"car"
,Car.
class
);
10.
System.out.println(
"car bean is ready for use!"
);
11.
car.introduce();
12.
}
13.
}
@DefaultSingletonBeanFactory提供一个Map集合实现的缓存器,用于缓存单实例Bean。
之前说到ApplicationContext是面向开发者的,那么来看看ApplicationContext:
ApplicationContext:
ApplicationContext是对BeanFactory的扩展,使用过程中常用的两个实现类
FileSystemXmlApplicationContext&&ClassPathXmlApplicationContext
ApplicationContext初始化:
01.
public
class
MyApplicationContext {
02.
03.
public
static
void
main(String[] args) {
04.
// 获取配置文件
05.
ApplicationContext cx =
new
ClassPathXmlApplicationContext(
06.
new
String[] {
"beans.xml"
});
//传入数组
07.
Person person = cx.getBean(
"person"
, Person.
class
);
08.
System.out.println(person);
09.
}
10.
}
@ApplicationContext在初始化的时候会实例化所有单例的Bean,非单例的Bean在调用时才实例化,区别在与scope=“singleton/prototype”所以初始化时间比BeanFactory长。
在xml中的监听器配置:
上述是在Java中手动获得ApplicationContext和BeanFactory,那么启动容器时,怎么加载这些配置文件呢?需要在xml中配置一个监听器了:
01.
<!-- 加载配置文件的路径信息 -->
02.
<
context-param
>
03.
<
param-name
>contextConfigLocation</
param-name
>
04.
<
param-value
>/WEB-INF/applicationContext.xml</
param-value
>
05.
<!--<param-value>classpath:applicationContext.xml</param-value> -->
06.
</
context-param
>
07.
08.
<
listener
>
09.
<
listener-class
>org.springframework.web.context.ContextLoaderListener</
listener-class
>
10.
</
listener
>
@配置文件路径同样支持Ant风格,监听器是常用的,还有一个通过Servlet自启动来实现。
Spring3新特性:基于Java类提供配置信息:
首先我们提供一个带有@Configuration注解的Java类:
01.
/**
02.
* 通过java类提供IoC配置信息
03.
*
04.
* @author PingCX
05.
*
06.
*/
07.
@Configuration
08.
// 告诉Spring这是一个bean提供类
09.
public
class
Beans {
10.
@Bean
(name =
"user"
)
11.
@Scope
(
"prototype"
)
12.
// 指定空间,默认是singleton,初始化时实例化,prototype在用到时实例化
13.
// 定义一个bean
14.
public
User createUser() {
15.
User user =
new
User();
16.
user.setUserName(
"ysjian"
);
17.
user.setUserId(
1001
);
18.
return
user;
19.
};
20.
21.
@Bean
(name =
"dataSource"
)
22.
public
BasicDataSource createDataSource() {
23.
BasicDataSource dataSource =
new
BasicDataSource();
24.
dataSource.setDriverClassName(
"com.mysql.jdbc.Driver"
);
25.
dataSource
26.
.setUrl(
"jdbc:mysql://localhost:3306/spring3?userUnicode=true&characterEncoding=UTF-8"
);
27.
dataSource.setUsername(
"root"
);
28.
dataSource.setPassword(
"ysjian"
);
29.
return
dataSource;
30.
}
31.
32.
@Bean
(name =
"jdbcTemplate"
)
33.
public
JdbcTemplate createjJdbcTemplate() {
34.
return
new
JdbcTemplate(createDataSource());
35.
}
36.
37.
@Bean
(name =
"transactionManager"
)
38.
public
DataSourceTransactionManager createdDataSourceTransactionManager() {
39.
return
new
DataSourceTransactionManager(createDataSource());
40.
}
41.
42.
@Bean
(name =
"userService"
)
43.
public
IUserService createUserService() {
44.
return
new
UserService();
45.
}
46.
47.
@Bean
(name =
"userDao"
)
48.
public
IUserDao createUserDao() {
49.
return
new
UserDao();
50.
}
51.
52.
@Bean
(name =
"loginLogDao"
)
53.
public
ILoginLogDao createLoginLogDao() {
54.
return
new
LoginLogDao();
55.
}
56.
}
启动容器,用到了AnnotationApplicationContext:
01.
public
class
AnnotationApplicationContext {
02.
03.
public
static
void
main(String[] args) {
04.
//Java类提供的配置信息
05.
ApplicationContext ctx =
new
AnnotationConfigApplicationContext(
06.
Beans.
class
);
07.
User user = ctx.getBean(
"user"
,User.
class
);
08.
System.out.println(user);
09.
}
10.
}
01.
<!-- 使用@Configuration的Java类提供配置信息 -->
02.
<
context-param
>
03.
<
param-name
>contextClass</
param-name
>
04.
<
param-value
>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</
param-value
>
05.
</
context-param
>
06.
<
context-param
>
07.
<
param-name
>contextConfigLocation</
param-name
>
08.
<!-- 指定J提供配置信息的Java类 -->
09.
<
param-value
>com.meritit.ysjian.spring3learning.context.Beans</
param-value
>
10.
</
context-param
>
11.
12.
<
listener
>
13.
<
listener-class
>org.springframework.web.context.ContextLoaderListener</
listener-class
>
14.
</
listener
>