Spring in Action 学习笔记
1 Spring 特点
a 非侵入式,一般基于spring开发的程序不依赖于Spring中的类。
b DI 依赖注入。又称ioc控制反转。这种设计模式强制 程学设计中使得类之间的关系解耦,使其类之间依赖接口定义
而非类定义 。这种设计模式有大量实例(bean)装配过程 ,单一重复 ,Spring用xml来简化这种依赖描述。主要使用
XmlBeanFactory 和 ApplicationContext 。学习细节就是bean如何用xml装配,和bean的生命周期。同时Spring提供了
很多有用的bean。可以直接使用。
c AOP 面向方面编程。AOP主要解决的问题是分离业务逻辑。如记录日志的功能在大多数业务里边需要,如果把这些代码
散落在各个业务逻辑里会造成大了重复代码,而且维护困难。如果使用AOP将使得记录日志功能分离出来,单独面向记
录日志这一个方面编程 使得以后的更改维护简单。对AOP的支持Spring提供了四种,1基于代理 2Jboss的AOP
3 AspectJ 4 Spring AOP。除了AspectJ 其他都是用代理类来实现的,也只能方法注入。
d Spring 还管理bean的生命周期。而且提供了很多基础功能,如数据库,事务管理,远程调用...
无论是DI还是AOP Spring用xml配置来实现,都依赖于java的reflection 。
2 Bean 的在Spring中的生成 组装。
a bean的生命周期由Spring控制,一次顺序 : 实例化--> 设置bean属性 --> 初始化Bean --使用--容器关闭销毁。
xml中可以一一配置其中的环节。
b 创建一个bean
因为DI要求的是接口依赖 所以创建按的Bean最好是实现某一接口的。
如:
public Interface CanDoSth{
void doSth() throws CanDoSthException;
}
public class SomeBody implements CanDoSth{
public void doSth() throws CanDoSthException{
System.out.println("done!!");
}
private String name="noname";
public void setName(String na){
name=na;
}
}
通过xml来配置生成一个bean,并为这个实例初始化name属性 如下
<bean id="people" class="SomeBody">
<property name="name" value="jack"/>
</bean>
c 装配bean ,如果两个bean 一个是car driveable 一个是somebody candrive。
public Interface CanDrive{
void drive() throws CanDrive Exception;
}
public class SomeBody implements CanDrive {
public void drive () throws CanDrive SthException{
driveable.drive();
}
private Driveable driveable;
public void setDriveable (Driveable da){
driveable = da;
}
}
public Interface Driveable{
void drive() throws CanDrive Exception;
}
public class Car implements Driveable {
public void drive () throws Driveable Exception{
System.out.println(" drive car ");
}
}
生成一个汽车xml
<bean id="acar" class="Car"/>
让jack驾驶这辆车
<bean id="people" class"SomeBody" >
<property name="driveable " ref="acar"/>
</bean>
实现了 Driveable接口的Train plane ..都可以直接替代car写在xml配置里。 这就是接口依赖的好处
bean依赖的注入方式 可以用setter 也可以用构造函数。
d 实现bean的装配集合 。
如果一个bean的属性是一个集合,如List Map xml如何配置?
<bean id="people" class"SomeBody" >
<property name="driveables " >
<list>
<ref bean="acar" />
<ref bean="atrain" />
<ref bean="aplane" />
</list>
</property>
</bean>>
e 通过设置bean的autowire属性 实现bean的Spring自动装配 。
f 通过设置bean 的scope属性实现bean实例的范围控制,生存周期。
1、 singleton ,即单例 bean
2、 prototype,不是单例bean 。
3、 request,这种 bean在 web的 request范围内有效,即每次请求时都会产生一个实例。只用于 web程序中。
4、 session,这种 bean在 web的 session范围内有效。只用于 web程序中 。
5、 global session,这种 bean在 web的全局 session范围内有效。只用于 web portlet框架中。
g bean可以通过实现不同的特定接口 来监听 或者和Spring容器交互。
3 AOP
Spring 通过实现一个代理类 来实现对目标类访问的织入。如图
加入类A是目标类 有dosth()方法。 为了在dosth调用前,或者调用后做一些事情比如记录一下调用时间在log上。
当然可以把log(time)的代码写到类A的dosth方法里。但这样会使代码不同功能混杂在一起难以维护和重用。做一个
代理类B 在调用dosth的时候 B先调用类C提供的记录时间的功能 然后再调用A的dosth()。这样就可以把记录log的工作
集中到类C里边。log的可以放入三个地方,调用前,调用后 ,异常后。在Spring中叫做“通知”
Spring如何在xml中定义实现这些:
首先 生成一个代理的bean proxy 他代理 beproxybean这个bean
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="beproxybean" />
<property name="interceptorNames" value="advisor" /> 这指明要代理的类的通知者,如上例就是类C的实例。
<property name="proxyInterfaces" value="beproxyInterface"/> 要被代理的接口
</bean>
通知者 是实现了某些接口的类。如实现了before ,afterReturning afterThrowing 方法 这样代理类会在调用被代理
类方法之前或之后调用相应的通知者的before afterReturning等方法。
一个接口可能有很多方法。上边proxyInterfaces指定了要代理一个接口,那么哪些方法需要调用时告诉通知者呢?这
需要在xml中配置通知者bean
<bean id="advisor" class="org.springframework.aop.support.RegexMehodPointcutAdvisor">
<property name="advice" ref="SomeAdvice"/>
<property name="pattern" ref="regpattern"/>
</bean>
pattern属性用正则表达式来确定接口中的哪些方法需要告诉通知者。(符和正则的方法名字)叫做切点。
Spring2.0中增加了纯粹的POJO切面。使得不需要定义通知者类 而且配置简单,增加了 AOP配置元素。