- Spring的作用及优势
Spring用于整合,好处是解耦。
解耦,可以降低组件与组件之间的关联,改善程序结构,便于系统的维护和扩展。
我们在使用Spring框架时,主要是使用Spring容器的两个特性:IoC和AoP。
IoC全称Inverse of Control(反向控制或控制反转)。
在类和类之间存在控制权,控制权指的是对象的创建和使用,
比如有类A和类B,我们之前的做法是在A中调用B,那么控制权就在A中,这样做的耦合度较高,
如果修改了B,A也要做相应修改。
引入Spring框架后,控制权由spring容器来负责。当A想使用B时,需要由Spirng容器通过
配置文件进行注入。这种思想就是IoC(为了更好的理解,我们可以这样认为,对象创建和使用
的控制权转移到了Spring容器,由Spring容器来控制)。
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程(也叫面向方面),
可以通过预编译方式和运行期动态代理实现在不修改源代码的前提下给程序动态统一添加功能的一
种技术。
Struts2中的拦截器,就是使用AOP的思想。使用AOP思想编写程序,会使程序更加灵活。
一般而言,使用Spring框架的主要作用:
我们会使用IoC整合组件(各种Bean),使用AOP来管理事务。
和Hibernate相同,Spring的使用也没有限制,到底是用于Web工程还是普通Java程序。 - Spring使用基础
2.1. Spring容器实例化
1) BeanFactory
XMLBeanFactory-->Resource--ClassPathResource\FileSystemResource
2) ApplicationContext(推荐)
ClassPathXmlApplicationContext
FileSystemXmlApplicationContext
2.2. Spring容器对Bean组件的管理
1) Bean对象创建的时机
默认是随着容器创建,可以使用lazy-init=true(在调用getBean创建)延迟创
也可以用<beans default-lazy-init="true"/>批量延迟创建
2) Bean对象的创建模式
默认是单例,可以使用scope属性改变。
singleton:单例,每次调用getBean返回同一个
prototype:原型,每次调用getBean返回一个新的
request:仅限于Web环境
session:仅限于Web环境
global session:仅限于Web环境
3) Bean对象初始化和销毁
init-method属性用于指定初始化方法
destroy-method属性用于指定销毁方法,仅适用于singleton模式 - scope属性的取值
在web(仅限于web项目)环境中,还可以设置所创建的bean对象的生命周期和
request、session
request 表示bean对象生命周期和request生命周期相同
session 同session
global session 相当于application
single
prototype
Bean对象的初始化和销毁
init-method属性用于指定初始化方法
destroy-method属性用于指定销毁方法,仅适用于singleton模式 - DI依赖注入
DI(依赖注入)是IoC实现的重要技术,有如下2中方式:
1) setter方式注入
2) 构造方式注入
注入类型有如下几种:简单值、集合、bean对象
Ioc和DI的关系?
我们认为Spring是具有IoC特性的框架。
实现IoC是由Spring容器来完成的,Spring容器通过依赖注入DI建立起对象(组件、Bean)
之间的关系。
我们可以这样理解:DI是IoC实现的一种手段,Ioc通过DI来实现。 - 注解方式配置
常用配置方式有XML文档配置,还有一种是通过注解方式配置。
采用注解方式的目的就是为了简化XML配置文件。
注解方式(也叫注释)是JDK5版本提供的,之前的版本不支持。
Spring2.5版本后支持注解方式,之前的版本不支持。
5.1组件自动扫描功能
首先需要在applicationContext.xml中添加<context:component-scan/>
1) 扫描Bean组件的注解,替代xml中的<bean>元素的定义。
@Service 用于Service业务组件
@Control 用于Action控制组件
@Respository 用于DAO数据访问组件
@Component 用于其他组件
Bean组件扫描到容器后,
默认名字为类名(首字母小写)如果需要自定义名称可以使用@Service("id名")
依赖注入的注解标记
@Resource 按名称@Resource(name="id名")
@AutoWired 按名称
@Autowired
@Qualifier("id名")
其他注解
@Scope 等价于<bean scope="">
@PostConstruct 等价于<bean init-method="">
@PreDestroy 等价于<bean destroy-method=""> - @Service("zhhellobean")相当于xml文件中配置<bean>
@Resource相当于xml文件中配置<property>
注解形式和xml形式各有优劣,注解方式现在比较流行。
注解方式的优点是使用方便,缺点是和Java代码掺和在一起,不好修改。
Xml方式的优点是修改方便,但是缺点是配置工作量较大。
注解方式的优点是使用方便,缺点是和Java代码掺和在一起,不好修改。
Xml方式的优点是修改方便,但是缺点是配置工作量较大。
7. 什么是AOP及其好处
Aspect Oriented Programming 面向方面编程或面向切面编程。
AOP关注点是共同处理,可以通过配置将其作用到某一个或多个目标对象上。好处是实现组件重复
利用,改善程序结构,提高灵活性。将共通组件与目标对象解耦。
8. AOP相关概念
1) Aspect切面(方面)
指的是共通业务处理,可以切入到多个目标对象,可多次使用
2) JoinPoint连接点
指的是切面组件在目标对象上作用的位置,
例如:方法上或者发生异常。
3) Pointcut切入点
切入点是连接点的集合,采用表达式指定
4) Target Object目标对象
5) Advice通知
指的是切面组件在连接点上执行的动作。
例如:在方法调用前、方法调用后、方法调用前后等。
6) AutoProxy动态代理
采用了AOP之后,容器返回的对象是代理对象。用户在使用时,由代理对象调用切面组件和
目标对象的功能。
a. 目标对象有接口采用JDK代理、
b. 目标对象没有接口采用CGLIB代理
Aspect Oriented Programming 面向方面编程或面向切面编程。
AOP关注点是共同处理,可以通过配置将其作用到某一个或多个目标对象上。好处是实现组件重复
利用,改善程序结构,提高灵活性。将共通组件与目标对象解耦。
8. AOP相关概念
1) Aspect切面(方面)
指的是共通业务处理,可以切入到多个目标对象,可多次使用
2) JoinPoint连接点
指的是切面组件在目标对象上作用的位置,
例如:方法上或者发生异常。
3) Pointcut切入点
切入点是连接点的集合,采用表达式指定
4) Target Object目标对象
5) Advice通知
指的是切面组件在连接点上执行的动作。
例如:在方法调用前、方法调用后、方法调用前后等。
6) AutoProxy动态代理
采用了AOP之后,容器返回的对象是代理对象。用户在使用时,由代理对象调用切面组件和
目标对象的功能。
a. 目标对象有接口采用JDK代理、
b. 目标对象没有接口采用CGLIB代理
9.<aop:aspect > 用于配置切面
id属性
ref属性 用于关联切面的bean
<aop:pointcut/>用于设置切入点
expression属性 类似于正则形式的表达式(后期讲,先使用)
execution()用于设置方法限定
execution(* tarena.service.*.*(..))
表示不限定返回类型,限定指定tarena.service包下的
所有方法,不限定参数类型
<aop:before> 表示采用before这种通知,作用于pointcut和方法上
id属性
ref属性 用于关联切面的bean
<aop:pointcut/>用于设置切入点
expression属性 类似于正则形式的表达式(后期讲,先使用)
execution()用于设置方法限定
execution(* tarena.service.*.*(..))
表示不限定返回类型,限定指定tarena.service包下的
所有方法,不限定参数类型
<aop:before> 表示采用before这种通知,作用于pointcut和方法上
10. 通知类型
1) 前置通知
<aop:before>
在目标方法调用之前执行。不能阻止后续执行,除非抛异常
2) 后置通知
<aop:after-returning>
在目标方法调用之后执行。目标方法正常结束才执行。
3) 最终通知
<aop:after>
在目标方法调用之后执行。目标方法正常或异常都执行。
异常通知
<aop:after-throwing>
在目标方法调用发生异常之后执行。
环绕通知
<aop:around>
在目标方法调用之前和之后执行。
这5种类型的通知,在内部调用时这样组织
try{
调用前置通知
环绕前置处理
调用目标对象方法
环绕后置处理
调用后置通知
}catch(Exception e){
调用异常通知
}finally{
调用最终通知
}
1) 前置通知
<aop:before>
在目标方法调用之前执行。不能阻止后续执行,除非抛异常
2) 后置通知
<aop:after-returning>
在目标方法调用之后执行。目标方法正常结束才执行。
3) 最终通知
<aop:after>
在目标方法调用之后执行。目标方法正常或异常都执行。
异常通知
<aop:after-throwing>
在目标方法调用发生异常之后执行。
环绕通知
<aop:around>
在目标方法调用之前和之后执行。
这5种类型的通知,在内部调用时这样组织
try{
调用前置通知
环绕前置处理
调用目标对象方法
环绕后置处理
调用后置通知
}catch(Exception e){
调用异常通知
}finally{
调用最终通知
}
11.切入点表达式用于指定目标对象及其作用位置。
1) execution方法限定
execution(modifiers-pattern?
ret-type-pattern
declaring-type-pattern?
name-pattern(param-pattern)
throws-pattern?)
execution(public * *(..))
表示无要求,只要是public修饰的方法就行
execution(* set*(..))
只要以set打头的方法,就可以。
execution(* com.xyz.service.AccountService.*(..))
匹配是这个类com.xyz.service.AccountService.*(..)下的所有方法
execution(* com.xyz.service.*.*(..))
匹配com.xyz.service这个包下的所有方法
execution(* com.xyz.service..*.*(..))
注意这个和上面的很像,就多个点儿,表示service及其子包下所有方法
(上面的不包括子包)
2) within类型限定
within(com.xyz.service.AccountService)
限定com.xyz.service.AccountService类中所有方法
和execution(* com.xyz.service.AccountService.*(..))效果相同
within(com.xyz.service.*)
限定com.xyz.service包下的所有方法(不包含子包)
within(com.xyz.service..*)
限定com.xyz.service包下的所有方法(包含子包)
3) this/target特定类型限定
实现AccountService接口的代理对象的任意连接点
this(com.xyz.service.AccountService)
实现AccountService接口的目标对象的任意连接点
target(com.xyz.service.AccountService)
注意this和target的区别
4) args方法参数类型限定
任何一个只接受一个参数,并且运行时所传入的参数是Serializable接口
args(java.io.Serializable)
5) bean对Bean对象名称限定
匹配bean对象名称以service结尾的对象bean(*service)
1) execution方法限定
execution(modifiers-pattern?
ret-type-pattern
declaring-type-pattern?
name-pattern(param-pattern)
throws-pattern?)
execution(public * *(..))
表示无要求,只要是public修饰的方法就行
execution(* set*(..))
只要以set打头的方法,就可以。
execution(* com.xyz.service.AccountService.*(..))
匹配是这个类com.xyz.service.AccountService.*(..)下的所有方法
execution(* com.xyz.service.*.*(..))
匹配com.xyz.service这个包下的所有方法
execution(* com.xyz.service..*.*(..))
注意这个和上面的很像,就多个点儿,表示service及其子包下所有方法
(上面的不包括子包)
2) within类型限定
within(com.xyz.service.AccountService)
限定com.xyz.service.AccountService类中所有方法
和execution(* com.xyz.service.AccountService.*(..))效果相同
within(com.xyz.service.*)
限定com.xyz.service包下的所有方法(不包含子包)
within(com.xyz.service..*)
限定com.xyz.service包下的所有方法(包含子包)
3) this/target特定类型限定
实现AccountService接口的代理对象的任意连接点
this(com.xyz.service.AccountService)
实现AccountService接口的目标对象的任意连接点
target(com.xyz.service.AccountService)
注意this和target的区别
4) args方法参数类型限定
任何一个只接受一个参数,并且运行时所传入的参数是Serializable接口
args(java.io.Serializable)
5) bean对Bean对象名称限定
匹配bean对象名称以service结尾的对象bean(*service)
12. AOP注解配置
1) 在xml配置中启用AoP注解配置
<aop:aspectj-autoproxy/>
2) 在切面组件中使用Aop注解
@Aspect
@Pointcut
@Before、@After、@AfterReturing、@AfterThrowing、@Around
1) 在xml配置中启用AoP注解配置
<aop:aspectj-autoproxy/>
2) 在切面组件中使用Aop注解
@Aspect
@Pointcut
@Before、@After、@AfterReturing、@AfterThrowing、@Around
13.Spring对数据库访问技术的支持
1) 对DAO提供了以下支持
一致的异常处理 DataAccessException
一致的DAO抽象类 DaoSupport、Template
2) 整合JDBC
a. 使用的API
JdbcDaoSupport
用于提供编写DAO组件的支持
JdbcTemplate
用于完成增删改查操作
update()
增删改操作
query()、queryForObject()、queryForInt等
查询操作
execute()
其他语句,例如建表、修改表结构语句
其他操作(了解)
批处理、返回自动增长主键值
b. XML配置
首先定义连接池<bean id="dataSource"/>之后将dataSource注入给所有DAO组件
3) 整合Hibernate
a. 使用的API
HibernateDaoSupport
提供编写DAO组件的支持
HibernateTemplate
提供了增删改查操作
save():保存
update():更新
delete():删除
find():查询
如果需要分页查询,可以使用HibernateDaoSupport提供的
this.getSession()方法获取Session对象。
b. XML配置
首先配置连接池dataSource
其次配置SessionFactory
最后将SessionFactory注入给所有DAO组件
1) 对DAO提供了以下支持
一致的异常处理 DataAccessException
一致的DAO抽象类 DaoSupport、Template
2) 整合JDBC
a. 使用的API
JdbcDaoSupport
用于提供编写DAO组件的支持
JdbcTemplate
用于完成增删改查操作
update()
增删改操作
query()、queryForObject()、queryForInt等
查询操作
execute()
其他语句,例如建表、修改表结构语句
其他操作(了解)
批处理、返回自动增长主键值
b. XML配置
首先定义连接池<bean id="dataSource"/>之后将dataSource注入给所有DAO组件
3) 整合Hibernate
a. 使用的API
HibernateDaoSupport
提供编写DAO组件的支持
HibernateTemplate
提供了增删改查操作
save():保存
update():更新
delete():删除
find():查询
如果需要分页查询,可以使用HibernateDaoSupport提供的
this.getSession()方法获取Session对象。
b. XML配置
首先配置连接池dataSource
其次配置SessionFactory
最后将SessionFactory注入给所有DAO组件
14.连接池的概念
连接池组件是干什么的?
连接池组件中管理的单元就是我们之前使用的Connection对象,在连接池中可以管理
Connection对象的创建和销毁,除此之外,连接池还可以控制和管理Connection对象
的数量。
连接池组件的优势:可以提高程序的稳定性;可以灵活的控制访问的连接数量
15.destroy-method="close"
指定销毁dataSource的方法,不是必须的,如果指定,能回收及时些连接池组件是干什么的?
连接池组件中管理的单元就是我们之前使用的Connection对象,在连接池中可以管理
Connection对象的创建和销毁,除此之外,连接池还可以控制和管理Connection对象
的数量。
连接池组件的优势:可以提高程序的稳定性;可以灵活的控制访问的连接数量
15.destroy-method="close"
<property name="initialSize" value="2">
表示连接池创建后,初始时有2个Connection
<property name="maxActive" value="10">
在连接池中最大创建10个Connection
<property name="minIdle" value="2">
表示最小的空闲数量,用于控制空闲的Connection的数量,表示最小空闲数量不能低于2个
<property name="maxIdle" value="3">
表示最大的空闲数量,表示最大空闲数量不能超过3个
如何使用dataSource?采用注入的方式(推荐使用set方式注入)