1、如何在纯java项目中使用spring
第一步:当然是新建一个java工程了,然后起一个好听的名字,新建的过程就略了吧,相信应该没有朋友不会吧。
第二步:添加所需要的包,你可以把所有的lib文件下的包都添加到你的工程里面去(不要以sources和javadoc结尾的包,这些不要不要!),别忘了一个关键的第三方包,它的名字叫做:commons-loggin-1.1.3.jar。这是一个jar包,是必须要有的,不然会报错
第三部:你可以选择设值注入还是构造注入两种方式来编写你的javabean了。spring将所有的东西都当做bean来操作,这样的好处是低耦合松散耦合,写代码更简单更方便啊。
首先写两个javabean,这两个javabean继承自他们的接口父类。
两个父类
public interface Knight {
public void embarkOnQuest();
}
public interface Quest {
void embark();
}
然后两个javabean实现父类
public class BraveKnight implements Knight{
private Quest quest;
public BraveKnight(Quest quest){
this.quest=quest;
}
public void embarkOnQuest(){
quest.embark();
}
}
public class SlayDragonQuest implements Quest{
public SlayDragonQuest(PrintStream stream) {
super();
this.stream = stream;
}
private PrintStream stream;
@Override
public void embark() {
// TODO Auto-generated method stub
stream.println("Embarking on quest to slay the dragon!");
}
}
接下来就是要在xml文档中配置这两个类了。我们仔细观察,发现我们的勇敢的骑士(BraveKnight)持有一个quest对象的引用,并在构造器中进行了初始化, 这就叫做构造注入了。那么xml中如何构造注入呢?
在src同级下创建一个bean.xml文件,名字随意,这里取名为bean。注意,你在哪里创建的,在写主函数的时候就要修改路径;下面的xml将System.out传给了quest
bean.xml文件的内容为:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="knight" class="cn.nju.fxd.spring.BraveKnight">
<constructor-arg ref="quest"/>
</bean>
<bean id="quest" class="cn.nju.fxd.spring.SlayDragonQuest">
<constructor-arg value="#{T(System).out}" />
</bean>
</beans>
好,下面我们写我们的测试程序,也就是main函数啦。
public class SpringTest {
public static void main(String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
BraveKnight braveKnight = (BraveKnight) ctx.getBean("knight",Knight.class);
braveKnight.embarkOnQuest();
}
}
可以看到,我们的main函数里面并没有new一个quest,然后传到bravekinght里面,也没有new 一个knight。这就是spring的神奇之处了,把工厂模式完全整合到spring里面去了,输出的内容是啥?你们自己猜猜看。
2.面向切面编程
上面讲了依赖注入的一个小例子,使用构造器注入,那么什么是面向切面编程呢?面向切面编程往往被定义为促使软件系统实现关注点分离的一项技术,系统由许多不同的组件组成,每一个组件各负责一块特定功能。除了实现自身核心的功能之外,这些组件还经常承担着额外的职责。注入日志、事务管理和安全这样的系统服务经常融入到自身具有核心业务逻辑的组件中去。这些系统服务通常被称为横切关注点,因为他们会跨越系统的多个组件。
如果讲这些关注点分散到多个组件中去,你的代码将会带来双重的复杂性。
(1)实现系统关注点功能的代码将会重复出现在多个组件中。这意味着如果你要改变这些关注点的逻辑,必须修改各个模块的相关实现。
(2)组件会因为那些与自身核心业务无关的代码而变得混乱。一个向地址簿增加地址条目的方法,应该只关注如何添加地址,而不应该关注它是不是安全的或者是否需要支持事物。
面向切面编程将系统服务模块坏,并以声明的方式将他们应用到他们需要影响的组件中去。所造成的的结果就是这些组件会具有更高的内聚性并且会更加关注自身的业务,完全不需要了解涉及系统服务所带来的的复杂性。总之,AOP能够确保POJO的简单性。
回到上面的例子,我们为我们上面的骑士增加一个记录者--吟游诗人。吟游诗人会记录骑士的勇敢事迹并进行传唱,我们创建一个Minstrel类,
public class Minstrel {
public Minstrel(PrintStream stream) {
super();
this.stream = stream;
}
private PrintStream stream;
public void singBeforeQuest(){
stream.println("Fa la la,the knight is so brave!");
}
public void singAfterQuest(){
stream.println("Tee hee hee,the brave knight did embark on a quest!");
}
}
正如你所看到的,Minstrel只有两个方法,singBeforeQuest方法在执行探险前被执行,singAfterQuest在执行探险后被调用,PrintSteam的引用出爱用构造器注入实现。
同时,BraveKnight如果要调用吟游诗人两个方法, 一般的思路是让吟游诗人加入到BraveKnight中去,成为它的一个成员变量即可,但是,按照面向对象的想法,BraveKnight针对需要一个吟游诗人吗?或者说,吟游诗人属不属于某个骑士呢?答案是确定的,吟游诗人不属于某个骑士。
我们可以将Minstrel声明为一个切面,在bean.xml中添加一个新bean,bean的class为Minstrel,并添加一个切面,如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<bean id="knight" class="cn.nju.fxd.spring.BraveKnight">
<constructor-arg ref="quest"/>
</bean>
<bean id="quest" class="cn.nju.fxd.spring.SlayDragonQuest">
<constructor-arg value="#{T(System).out}" />
</bean>
<bean id="minstrel" class="cn.nju.fxd.spring.Minstrel">
<constructor-arg value="#{T(System).out}"/>
</bean>
<aop:config>
<aop:aspect ref="minstrel">
<!-- 定义切点为embarkOnQuest方法 -->
<aop:pointcut expression="execution(* *.embarkOnQuest(..))" id="embark"/>
<aop:before method="singBeforeQuest" pointcut-ref="embark"/>
<aop:after method="singAfterQuest" pointcut-ref="embark"/>
</aop:aspect>
</aop:config>
</beans>
当然光实现上面那样是不行的,你需要额外的第三方包支持,哪几个呢?
aopalliandce-alpha1.jar,aspectjrt.jar,aspectjweaver.jar另外要切记,千万注意大小写和拼写错误!!
3.容纳你的bean--spring容器
在基于Spring的应用中,你的应用对象生存于spring容器中,容器负责创建对象,装配他们,配置并管理他们的整个生命周期,从生存到死亡。spring容器并不是只有1个,spring自带了多个容器的实现,可以归为两种不同的类型。bean工厂类型是最简单的容器,提供基本的DI支持。应用上下文容器基于BeanFactory构建,并提供应用框架级别的服务,例如从属性文件解析文本信息以及发布应用事件给感兴趣的事件监听者。
3.1使用应用上下文
spring自带了多种类型的应用上下文,下面的几个可能是你最有可能遇到的。
(1)AnnotationConfigApplicationContext:从一个或多个基于java的配置类中加载spring应用上下文
(2)AnnotationConfigWebApplication:从一个或多个基于java的配置类中加载Spring Web应用上下文。
(3)ClassPathXmlApplicationContext:从类路径下的一个或者多个xml配置文件中加载上下文定义,把应用上下文的定义文件作为类资源。
(4)FileSystemXmlApplicationContext:从文件系统下的一个或多个xml配置文件中加载上下文定义
(5)XmlWebApplicationContext:从Web应用下的一个或多个xml配置文件中加载上下文定义。
我们前面已经使用过ClassPathApplicationContext了。
3.2bean的生命周期
spring容器中的bean生命周期要比传统java应用的bean要复杂的多。
如上图所示,bean继续之前,bean工厂执行了若干的启动步骤,上图步骤详细描述如下:
(1)spring对bean进行实例化
(2)spring将值和bean的引用注入到bean对应的属性中;
(3)如果bean实现了BeanNameAware接口,spring将bean的id传递个setBean-Name()方法;
(4)如果bean实现了BeanFactoryAware接口,spring将调用setBeanFactory()方法,将BeanFactory容器实例传入;
(5)如果bean实现了ApplicationContextAware接口,spring将调用setApplicationContext()。
如果 bean 实现 了 BeanPostProcessor 接口, Spring 将 调 用它 们 的 postProcessBeforeInitialization() 方法;
如果 bean 实现 了 InitializingBean 接口, Spring 将 调 用它 们 的 afterPropertiesSet() 方法。 类 似地,如果 bean 使用 init-method 声明了初始化方法, 该 方法也会被 调 用;
如果 bean 实现 了 BeanPostProcessor 接口, Spring 将 调 用它 们 的 postProcessAfterInitialization() 方法;
此 时 , bean 已 经 准 备 就 绪 ,可以被 应 用程序使用了,它 们 将一直 驻 留在 应 用上下文中,直到 该应 用上下文被 销 毁 ;
如果 bean 实现 了 DisposableBean 接口, Spring 将 调 用它的 destroy() 接口方法。同 样 ,如果 bean 使用 destroy-method 声明了 销 毁 方法, 该 方法也会被 调 用。
3俯瞰Spring风景线
3.1Spring模块
当我 们
下
载
Spring
发
布版本并
查
看其
lib
目
录时
,会
发现
里面有多个
JAR
文件。在
Spring 4.0
中,
Spring
框架的
发
布版本包括了
20
个不同的模
块
,每个模
块
会有
3
个
JAR
文件(二
进
制
类库
、源
码
的
JAR
文件以及
JavaDoc
的
JAR
文件)
这 些模
块
依据其所属的功能可以划分
为
6
类
不同的功能,如
图
1.7
所示
Spring核心容器
容器是 Spring
框架最核心的部分,它管理着
Spring
应
用中
bean
的
创
建、配置和管理。在
该
模
块
中,包括了
Spring bean
工厂,它
为
Spring
提供了
DI
的功能。基于
bean
工厂,我
们还
会
发现
有多种
Spring
应
用上下文的
实现
,每一种都提供了配置
Spring
的不同方式。除了
bean
工厂和
应
用上下文,
该
模
块
也提供了
许
多企
业
服
务
,例如
E-mail
、
JNDI
访问
、
EJB
集成和
调
度。
Spring的AOP模块
在 AOP
模
块
中,
Spring
对
面向切面
编
程提供了丰富的支持。
这
个模
块
是
Spring
应
用系
统
中开
发
切面的基
础
。与
DI
一
样
,
AOP
可以帮助
应
用
对
象解耦。借助于
AOP
,可以将遍布系
统
的关注点(例如事
务
和安全)从它
们
所
应
用的
对
象中解耦出来。
数据访问与集成使用
使用 JDBC
编
写代
码
通常会
导
致大量的
样
板式代
码
,例如
获
得数据
库连
接、
创
建
语
句、
处
理
结
果集到最后关
闭
数据
库连
接。
Spring
的
JDBC
和
DAO
(
Data Access Object
)模
块
抽象了
这
些
样
板式代
码
,使我
们
的数据
库
代
码变
得
简单
明了,
还
可以避免因
为
关
闭
数据
库资
源失
败
而引
发
的
问题
。
该
模
块
在多种数据
库
服
务
的
错误
信息之上构建了一个
语义
丰富的异常
层
,以后我
们
再也不需要解
释
那些
隐
晦
专
有的
SQL
错误
信息了!
对
于那些更喜
欢
ORM
(
Object-Relational Mapping
)工具而不愿意直接使用
JDBC
的开
发
者,
Spring
提供了
ORM
模
块
。
Spring
的
ORM
模
块
建立在
对
DAO
的支持之上,并
为
多个
ORM
框架提供了一种构建
DAO
的
简
便方式。
Spring
没有
尝试
去
创
建自己的
ORM
解决方案,而是
对许
多流行的
ORM
框架
进
行了集成,包括
Hibernate
、
Java Persisternce API
、
Java Data Object
和
iBATISSQL Maps
。
Spring
的事
务
管理支持所有的
ORM
框架以及
JDBC
。
Web与远程调用
MVC (
Model-View-Controller
)模式是一种普遍被接受的构建
Web
应
用的方法,它可以帮助用
户
将界面
逻辑
与
应
用
逻辑
分离。
Java
从来不缺少
MVC
框架,
Apache
的
Struts
、
JSF
、
WebWork
和
Tapestry
都是可
选
的最流行的
MVC
框架。
虽
然
Spring
能
够
与多种流行的
MVC
框架
进
行集成,但它的
Web
和
远
程
调
用模
块
自
带
了一个
强
大
的 MVC 框架,有助于在
Web
层
提升
应
用的松耦合水平。
Instrumentation
Spring 的
Instrumentation
模
块
提供了
为
JVM
添加代理(
agent
)的功能。具体来
讲
,它
为
Tomcat
提供了一个
织
入代理,能
够为
Tomcat
传递类
文件,就像
这
些文件是被
类
加
载
器加
载
的一
样
。如果
这
听起来有点
难
以理解,不必
对
此
过
于担心。
这
个模
块
所提供的
Instrumentation
使用
场
景非常有限
测试
鉴 于开
发
者自
测
的重要性,
Spring
提供了
测试
模
块
以致力于
Spring
应
用的
测试
。通
过该
模
块
,你会
发现
Spring
为
使用
JNDI
、
Servlet
和
Portlet
编
写
单
元
测试
提供了一系列的
mock
对
象
实现
。
对
于集成
测试
,
该
模
块为
加
载
Spring
应
用上下文中的
bean
集合以及与
Spring
上下文中的
bean
进
行交互提供了支持。
3.2 Spring Portfolio