1.Spring框架作用和优点
Spring框架主要负责进行技术整合,例如整合Struts2、Hibernate、JDBC等技术。
优点是:可以提高程序结构灵活性、降低组件之间的耦合度,便于日后的扩展和维护。
2.Spring框架主要功能
a.Spring框架提供了一个核心容器,该容器可以负责管理程序中的DAO、Action等组件
*b.Spring框架提供了对Struts2、Hibernate、JDBC技术整合的API
c.Spring框架提供了IOC机制,可以降低两个组件之间调用的耦合度
d.Spring框架提供了AOP机制,可以降低共通组件和一批目标组件的耦合度。
*e.Spring框架提供了事务管理功能,只需要做一些AOP配置即可。
3.Spring框架容器
Spring框架容器可以管理DAO、Action等Bean组件。该容器具有以下功能:
a.可以创建Bean组件对象
b.可以初始化Bean组件对象
c.可以销毁Bean组件对象
d.容器具有IOC和AOP机制
*1)Spring容器基本使用步骤
--引入spring-ioc开发包
--在src下添加applicationContext.xml配置
--将DAO等组件定义到applicationContext.xml中,定义格式
1. <bean id="标识符" class="包名.类名"> 2. </bean>
--实例化Spring容器对象
BeanFactory-->ApplicationContext(子类)
new ClassPathXmlApplicationContext(容器配置文件);
--通过容器对象.getBean(标识符)获取Bean实例。
2)Spring容器对Bean管理的基本特性
*a.Bean对象创建
默认支持singleton和prototype两种,即单例和多例。可以使用scope属性指定,属性默认值是singleton。
如果应用Web程序中,通过配置可以扩展出request,session等属性值。
b.Bean对象初始化
可以通过init-method属性指定方法名。将来在创建Bean对象时自动调用该方法执行初始化逻辑。
c.Bean对象销毁
可以通过destroy-method属性指定方法名。将来该对象被垃圾回收前自动调用该方法执行资源释放工作。
该属性仅对scope="singleton"单例Bean对象有效。当执行Spring容器close()时,容器会释放Bean单例对象,会触发destroy-method指定的方法。
d.Bean对象创建时机
scope="singleton"是在容器实例化时创建。scope="prototype"是在getBean()时创建。利用lazy-init="true"可以将singleton组件创建推迟到getBean方法调用。
*4.Spring框架的IOC机制
IOC解决两个Bean组件调用问题,可以降低两个Bean组件对象之间的耦合度。
1)IOC概念
Inverse of Controller称为控制反转或反向控制。
所谓控制指的是对象的创建、初始化和销毁过程。当一个组件发生变更后,该逻辑需要相应修改。
控制反转确切讲应该是控制的转移,意思是将控制逻辑由使用一方转移到第三框架或容器负责。当再发生组件变更后,只需要修改框架或容器配置,不需要修改关联组件。
2)DI概念
Dependency Injection 依赖注入。
依赖注入技术是Spring实现IoC控制思想的方法。
DI在Spring中有两种注入方法:
*a.setter方式注入
依靠set方法将组件对象传入。
--在使用一方添加属性变量和set方法
--在使用一方<bean>定义部分,添加
<property name="属性名"
ref="要注入的Bean对象id值">
</property>
b.构造方式注入
依靠构造方法将组件对象传入。
--在使用一方添加带参数的构造方法
--在使用一方<bean>定义部分,添加
1. <constructor-arg index="参数索引" 2. ref="要注入的Bean对象id值"> 3. </constructor-arg>
3)各种类型的注入
Spring的DI可以注入各种类型数据,常见的有以下几种:
*a.Bean组件对象注入
利用ref属性指定要注入的Bean对象id.
1. <property name="属性名" ref="id值"> 2. </property>
b.基本数据注入
注入一个字符串、数值
<property name="属性名" value="值">
</property>
c.List集合注入
d.Set集合注入
e.Map集合注入
f.Properties注入
5.AOP概念
Aspect Oriented Programming 面向方面编程。
OOP是面向对象编程,编程侧重点对象。
AOP面向方面编程,侧重点是方面,方面指的是共通处理的组件,需要被其他多个组件调用。AOP是OOP编程为基础。
AOP主要解决问题是:共通组件与其他组件以低耦合方式关联。
AOP编程需要涉及以下几个重要概念:
*1)方面(Aspect)
指的是共通处理组件,需要作用到其他目标组件的处理方法上的。
*2)切入点(Pointcut)
用于指定哪些组件或方法追加方面组件功能。可以用切入点表达式指定
*3)通知(Advice)
用于指定方面组件和目标组件作用的时机和位置。
4)目标组件(Target)
切入点表达式指定的组件就是目标组件。
5)连接点(JoinPoint)
切入点是连接点的集合。连接点指的是方面组件与某一个目标组件相结合的信息。通过该对象可以获取目标组件类型和方法等信息。
6)动态代理(AutoProxy)
Spring框架采用动态代理技术实现AOP机制。
Spring如果使用AOP配置,容器返回的Bean对象是采用动态代理技术生成的一个新类型,该新类型组件在内部会去调用方面组件和原目标组件的功能。
Spring框架采用两种动态代理技术。
a.CGLIB技术
针对没有接口实现的目标组件。采用继承方法生成一个子类
1. public class Action$$EnhancerByCGLIB$234 2. extends 原Action组件类型{ 3. //重写execute业务方法, 4. //调用方面和目标组件功能 5. }
b.JDK Proxy API技术
针对有接口实现的目标组件。采用实现原目标接口的方法生成一个类型
1. public class 新类型 2. implements 原目标组件接口{ 3. //重写接口业务方法, 4. //调用方面和目标组件功能 5. }
Spring通知类型
通知可以指定方面组件和目标组件的执行顺序,Spring提供了以下5种类型通知。
1)前置通知(aop:before)
先执行方面处理,再执行目标组件处理
2)后置通知(aop:after-returning)
先执行目标组件,没抛出异常,再执行方面组件。如果目标有异常,不会执行方面组件
3)最终通知(aop:after)
先执行目标组件,不管有没有异常,都要执行方面组件。
4)异常通知(aop:after-throwing)
先执行目标组件,如果抛出异常才会执行方面组件。没有抛出异常不会执行。
5)环绕通知(aop:around)
先执行方面组件前置部分,在执行目标组件,最后执行方面组件后置部分。等价前置+后置结构。
1. try{ 2. //前置通知执行--方面组件 3. //执行目标组件处理 4. //后置通知执行--方面组件 5. }catch(){ 6. //异常通知执行--方面组件 7. }finally{ 8. //最终通知执行--方面组件 9. }
切入点
切入点是用一个表达式表示,用于指定目标及其方法。
*1)方法限定
可以指定哪些方法启用方面组件功能。
execution(修饰符? 返回类型 方法名(参数列表) throws异常?)
示例1:匹配容器中所有Bean对象的find开始的方法
execution(* find*(..))
示例2:匹配容器中CostDAO组件的find开始的方法
execution(*
org.tarena.dao.CostDAO.find*(..))
示例3:匹配容器中在dao包中的所有类的所有方法
execution(* org.tarena.dao.*.*(..))
示例4:匹配容器中在dao包及其子包中所有类的所有方法
execution(* org.tarena.dao..*.*(..))
*2)类型限定
指定哪些类型组件的所有方法启用方面功能。
within(包名.类型)
示例1:匹配容器中CostDAO组件的所有方法
within(org.tarena.dao.CostDAO)
示例2:匹配容器中action包下的所有类的所有方法
within(org.tarena.action.*)
示例3:匹配容器中action包及其子包中所有类的所有方法
within(org.tarena.action..*)
*3)Bean名称限定
可以通过id属性进行限定,指定哪些id的Bean对象启用方面功能.
bean(id属性值)
示例1:匹配容器中id=jdbcCostDAO的Bean对象的所有方法
bean(jdbcCostDAO)
示例2:匹配容器中所有id以DAO结尾的Bean对象的所有方法
bean(*DAO)
4)参数限定
可以指定方法参数列表限定目标组件和方法。
args(参数列表)
示例:匹配容器中所有Bean的方法,仅有一个参数,而且参数类型是符合List类型的
args(java.util.List)
注意:上述限定表达式可以组合应用,利用&&,||运算符连接。
6.Spring注解配置方法
注解配置是从JDK5.0开始支持,Spring2.5及其以上版本可以采用的一种配置方法。
注解配置优点是简单、方便。可以替代applicationContext.xml中大量的XML定义。
注解其实是在类前、方法前、成员变量前放置的一些特殊标记。
1)Spring组件扫描
可以扫描包路径下所有组件,当发现组件类定义前有以下注解标记,会将该组件纳入Spring容器。等价于XML配中的<bean>定义
--@Component (其他组件应用)
--@Controller (Action组件应用)
--@Service (Service业务组件应用)
--@Repository (DAO组件应用)
a.组件扫描技术使用方法如下:
--在applicationContext.xml中开启组件扫描应用
<context:component-scan
base-package="扫描包路径"/>
--在Action或DAO等组件前使用上述注解标记
--通过容器.getBean()方法获取Bean对象。默认使用类名首字母小写充当id值。如果需要自定义id,可以采用@Repository("id值")
b.其他<bean>属性注解标记:
@Scope("prototype或singleton")等价于scope属性
@PreDestroy等价于destroy-method属性
@PostConstruct等价于init-method属性
2)IOC注入注解
在成员变量或setter方法前,定义@Resource或@Autowired注解标记。默认都可以按照类型匹配注入。
如果有多个Bean对象都匹配注入,需要指定注入的id值。使用格式如下:
--@Resource(name="要注入的id值")
--@Autowired
@Qualifier("要注入的id值")
3)AOP注解配置
注解配置使用方法如下:
--在applicationContext.xml中开启AOP注解配置。
<aop:aspectj-autoproxy />
--在方面组件中使用下面注解
@Component//将组件扫描到Spring容器
@Aspect //将该组件定义成方面组件
--在方面组件中定义一个空方法,利用@Pointcut标记定义切入表达式
@Pointcut("切入点表达式")
public void mypoint(){}
--在方面组件共通方法上,利用通知注解标记切入。
@Before前置通知
@AfterReturning后置通知
@After最终通知
@AfterThrowing异常通知
@Around环绕通知
7.Spring与Struts2整合
1)引入struts-spring-plugin.jar开发包
(可以访问Spring容器,利用<action>配置的class属性值去Spring容器中寻找Bean对象)
2)将Action定义到Spring容器中,id值与<action>的class属性值保持一致
3)在web.xml中定义ContextLoaderLisener
(在服务器启动时,用于实例化Spring容器对象)
4)在web.xml中采用<context-param>指定Spring容器配置文件位置
2.strut2-spring-plugin.jar整合包
在Struts2框架中有一个ObjectFactory组件,负责Struts2中Action等组件对象的创建。
strut2-spring-plugin.jar包中也提供了一个StrutsSpringObjectFactory组件,并且将struts框架的struts.objectFactory设置成了StrutsSpringObjectFactory。因此Struts再接收请求后,会利用StrutsSpringObjectFactory获取Action对象,在StrutsSpringObjectFactory中,提供了一个获取Action对象的方法,该方法主要逻辑如下:
1. try{ 2. //获取web.xml中lisener创建的Spring容器对象 3. ApplicationContext ac = ...; 4. //调用ac.getBean()获取Spring容器的Bean对象。用class属性去寻找 5. Object action = ac.getBean(class属性值) 6. //将返回的action对象交给struts框架处理请求 7. }catch(Exception ex){ 8. //当利用class属性在容器中找不到对应的Bean,执行下面流程。 9. //采用反射机制生成一个Action对象 10. Class class = Class.forName("org.tarena.action.HelloAction1"); 11. Object action = class.newInstance(); 12. //访问Spring容器,将容器中id名称与Action对象属性名称相同的Bean对象,给Action注入。 13. //将action返回交给struts框架处理请求 14. }
8.Spring事务管理
Spring框架提供了事务管理功能,可以采用以下两种方式:
*1)声明式事务管理(基于AOP配置控制)
a.基于XML配置
//具体配置参考NETCTOSS-SSH的applicationContext.xml示例。
提示:如果Action作为目标对象切入事务,需要在<aop:config>元素里添加proxy-target-class="true"属性。原因是通知Spring框架采用CGLIB技术生成具有事务管理功能的Action类。
*b.基于注解配置
--在applicationContext.xml中开启事务注解配置。
1. <bean id="txManager" class="..."> 2. <property name="sessionFactory" ref="..."> 3. </property> 4. </bean> 5. <tx:annotation-driven transaction-manager="txManager"/><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
--在目标组件类中使用@Transactional,该标记可以定义在类前或方法前
2)编程式事务管理(基于Java编程控制)
利用TransactionTemplate将多个DAO操作封装起来,当作一个完整事务控制。
2.Spring MVC框架应用
1)Spring MVC框架主要组件
a.DispatcherServlet
主控制器,等价于Struts的Filter
b.Controller
业务控制器,等价于Struts的Action
c.HandlerMapping
映射处理器,负责维护请求和Controller之间的对应关系。
d.ViewResolver
视图解析器,负责根据视图信息寻找视图组件。
e.ModelAndView
模型和视图组件,负责存储视图标识和响应界面需要的模型数据
2)Spring MVC处理流程
a.客户端发送请求,请求首先到达DispatcherServlet主控制器。
b.主控制器调用HandlerMapping组件,根据请求和Controller映射信息,寻找相应的Controller组件处理。
c.执行Controller组件约定的业务处理方法,如果需要数据库操作,可以在业务方法中调用DAO组件。业务方法执行完毕,会返回一个ModelAndView对象。
d.主控制器调用ViewResolver解析ModelAndView对象,根据视图标识信息定位视图JSP组件。
e.将JSP解析生成响应界面,给浏览器返回。
3)Spring MVC基本应用
示例1:
hello.do-->HelloController
-->/WEB-INF/jsp/hello.jsp
示例实现步骤如下:
a.引入spring的ioc和webmvc开发包
b.在src下引入spring配置文件applicationContext.xml
c.在web.xml中配置主控制器DispatcherServlet,指定spring配置文件位置和名称.
d.编写HelloController组件,注意实现Controller接口
e.在spring配置文件中定义HelloController组件、HandlerMapping组件、ViewResolver组件
f.在WEB-INF/jsp下添加hello.jsp页面