Spring随笔

作者: JHMichael | 来源:发表于2017-05-21 15:40 被阅读93次

1、Spring简介:
Spring是一个IOC(DI)和AOP容器框架
轻量级:Spring是非侵入性的,基于开发的应用中的对象可以不依赖与Spring的API
依赖注入(DI - Dependency injection、IOC)
面向切面编程(AOP - aspect oriented programming)
容器:Spring是一个容器,因为其包含并且管理应用对象的生命周期
框架:Spring实现了使用简单的组建配置组合成一个复杂的应用,在Spring中可以使用XML和Java注解组合这些对象
一站式:在IOC和AOP的基础上可以整个各种企业应用的开源框架和优秀的第三方类库(Spring自身提供了展现层SpringMVC与持久层Spring JDBC)
2、Spring模块:

Spring
3、搭建Spring开发环境:
导入jar包:
commons-logging.jar(Spring依赖的jar包)
spring-beans.RELEASE.jar
spring-context-RELEASE.jar
spring-core.RELEASE.jar
spring-expression.RELEASE.jar
spring-aop.RELEASE.jar
Spring的配置文件:一个典型的spring文件项目需要创建一个或多个Bean配置文件,这些配置文件用于在SpringIOC容器里配置Bean.Bean的配置文件可以放在classpath下,也可以放在其他目录下
4、Spring的设置基本步骤:
类路径下创建配置文件:applicationContext.xml(配置bean)
<bean id="customer" class="com.djh.demo.Customer">
<property name="cusName" value="Tom"></property>
</bean>
在java Code中加入以下步骤注入bean
创建Spring的IOC的容器对象:
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
从IOC容器中获取Bean的实例
Customer customer = ctx.getBean("customer");
5、Spring Bean的配置
配置形式:
基于XML文件的方式
基于注解的方式
Bean的配置方式:
通过全类名(反射)
通过工厂方法(静态工厂方法&实例工厂方法)
FactoryBean
IOC容器BeanFactory & ApplicationContext概述
依赖注入的方式:
属性注入
构造器注入
注入属性值细节
自动专配
bean之剑的关系:
继承
依赖
bean的作用域:
singleton
prototype
WEB环境作用域
使用外部属性文件
在Spring的IOC容器里配置Bean:
在xml文件中通过bean节点来配置bean
<bean id="customer" class="com.djh.demo.Customer">
<property name="cusName" value="Tom"></property>
</bean>
id:Bean的名称
在IOC容器中必须是唯一的
若id没有指定, Spring自动将权限定性类名作为Bean的名字
id可以指定多个名字,之间用逗号、分号或空格分隔
Spring提供的两种类型的IOC容器实现:
BeanFactory:IOC容器的基本实现
ApplicationContext:提供了更多的高级特性,为BeanFactory的子接口
ApplicationContext的主要实现类:
ClassPathXmlApplicationContext:从类路径下加载配置文件
FileSystemXmlApplicationContext:从文件系统中加载配置文件
ApplicationContext在初始化上下文时就实例化所有单例的Bean
依赖注入的方式(3种):
属性注入(即setter方法)
属性注入使用<property>元素,使用name属性执行Bean的属性名称,value属性或<value>子节点指定属性值
如:
<bean id="customer" class="com.djh.demo.Customer">
<property name="cusName" value="Tom"></property>
</bean>
构造器注入
在<constructor-arg>元素里声明,<constructor-arg>中没有name属性
<bean id="customer" class="com.djh.demo.Customer">

<constructor-arg value="Tom" index="0" type="java.lang.String"></constructor-arg>
</bean>
工厂方法注入
对于注入的值包含特殊字符,如:<, >等,需要使用<![CDTAT[xxx]]>来表示
引用其他的Bean:
在Bean的配置文件中,可以通过<ref>元素或ref属性为Bean的属性或构造器参数指定对Bean的作用
也可以在属性或构造器里包含Bean的声明,这样的Bean称为内部Bean,不能被外部引用
注入null值与级联属性:
可以使用<null/>元素标签为Bean的字符串或其他对象类型的属性注入null值
SSH均支持级联属性的配置,如:
<property name="customer.cusName" value="Michael" />
对于集合类型的属性,使用list、set或map标签方式,如下:
<property name="customers">
<list>
<ref bean="customer1" /> //或<value>Jacky</value>
<ref bean="customer2" />
</list>
</property>
<map>标签里可以有多个<entry>子标签,每个条目包含一个key与value,简单常量使用key与value来定义,Nean引用通过key-ref与value-ref属性定义
使用<props>定义java.util.Properties,该标签使用多个<prop>作为子标签,每个<prop>标签必须定义key属性
5、Spring自动装配:
Spring IOC容器可以自动装配Bean,需要做的仅仅是在<bean>的autowire属性里指定自动装配的模式
byType(根据类型自动装配):Spring IOC 容器中不能有多个与目标Bean类型一致的Bean
byName(根据名称自动装配):必须将目标Bean的名称和属性名设置的完全相同
Bean的名称与setter方法的名称一致的,如:
Person Bean:
class Person{
private String personName;
private Address address;
//Getter and Setter method
}
Address Bean:
class Address{
private String street;
//Getter and Setter method
}
configure file:
<bean id="address" class="com.djh.demo.Address">
<property name="street" value="TianHe" />
</bean>
<bean id="person" class="com.djh.demo.Person" autowire="byType">
<property name="personName" value="Michael" />
</bean>
constructor(通过构造器自动装配)
Spring的Bean之间的关系:
继承(parent属性),如:Customer{String:custName, int:age}
<bean id="customer" class="com.djh.demo.Customer">
<property name="age" value="20" />
<property name="custName" value="Lucy" />
</bean>
<bean id="customer2" parent="customer">
<property name="custName" value="Michael" />
</bean>
依赖(depends-on属性)
Spring允许通过depeds-on属性设定Bean前置依赖的Bean,前置依赖的Bean会在本Bean实例化之前创建好
如果前置依赖于多个Bean,则可以通过逗号、空格的方式配置Bean的名称
Spring中Bean的作用域:
使用scope属性进行配置
作用域有以下四个,默认为singleton
prototype:容器初始化时不会创建Bean实例,而是在每次请求创建Bean的实例时返回
request
session
singleton:创建IOC容器(ApplicationContext)时就创建了Bean实例,单例的
如:
<bean id="customer" class="com.djh.demo.Customer" scope="prototype">
<property name="custName" value="djh" />
</bean>
使用外部属性文件:
Spring提供了一个PropertyPlaceholderConfigurer的BeanFactory后置处理器,该处理器允许用户将Bean的部分内容移到属性文件中,可以在Bean配置文件中使用形式为${var}的变量,PropertyPlaceholderConfigurer从属性文件里加载属性,并使用这些属性来替换变量
Spring还允许在属性文件中使用${propName},以实现属性之间的相互引用
注册PropertyPlaceholderConfigurer
Spring2.0:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:database.properties" />
</bean>
Spring2.5:
通过<context:property-placeholder>元素
<beans>中添加context Schema定义,即加入context的Namespaces
在配置文件中加入如下配置:
//导入配置文件
<context:property-placeholder location="classpath:database.properties" />
//导入后可以使用${key}的形式访问配置文件中对应的value
6、SpEL
一个支持运行时查询和操作对象的表达式语言
语法类似于EL,使用#{xxx}作为定界符,所有在大括号中的字符都被认为是SpEL
SpEL为bean的属性进行动态复制提供了便利
SpEL可以实现如下功能:
通过bean的id对bean进行引用
调用方法以及引用对象中的属性
计算表达式的值
正则表达式的匹配
SpEL字面量:
整数:
<property name="count" value="#{5}" />
小数:
<property name="frequency" value="#{88.2}" />
科学计数法:
<property name="capacity" value="#{1e4}" />
String可以使用单引号或者双引号作为字符串的定界符:
<property name="name" value="#{'djh'}" />
<property name="count" value='#{"Lucy"}' />
Boolean:
<property name="display" value="#{true}" />
SpEL引用Bean、属性与方法:
引起其他对象(Bean):

<property name="prefix" value="#{prefixGenerator}" />
引用其他对象的属性:
<property name="stuffix" value="#{prefixGenerator.stuffix}" />
通过其他方法,还可以链式操作:

<property name="stuffix" value="#{prefixGenerator.toString()}" />

<property name="stuffix" value="#{prefixGenerator.toString().toUpperCase()}" />
调用静态方法或静态属性:通过T()调用一个类的静态方法,返回一个类对象
<property name="initValue" value="#{T(java.lang.Math).PI}" />
7、Spring工厂方法配置Bean
调用静态工厂方法创建Bean是将对象创建的过程封装到静态方法中
要声明通过静态方法创建的Bean,需要在Bean的class属性里指定拥有该工厂方法的类,同时在factory-method属性里指定工厂方法的名称,最后使用<constructor-arg>元素为该方法传递方法参数
FactoryBean(接口):
getObject():返回bean对象
getObjectType():返回bean的类型
isSingleton():返回bean是否单例
8、注解配置Bean:
在classpath中扫描组件
Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件
特定组件包括以下几个:
@Component:基本注解,标识了一个受Spring管理的组件
@Repository:标识持久层组件
@Service:标识服务层(业务层)组件
@Controller:标识表现层组件
对于扫描到的组件,Spring有默认的命名策略,使用非限定类名,第一个字母小写,也可以在注解中通过value属性值标识组件的名称
当在组件类上使用了特定的注解之后,还需要在Spring的配置文件中声明<context:component-scan>:
base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及其子包中的所有类
当需要扫描多个包时,可以使用逗号分隔
如果仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类,如:
<context:component-scan
base-package="com.djh.demo.spring.beans"
resource-pattern="autowire/*.class" />
如下所示:
结构:
Structor
配置文件:
Configuration
各个类的注解:
Person.java:
Annotation
MockController.java:
Annotation
DataBaseMockImp.java:
Annotation
ServiceMock.java:
Annotation
测试结果:
result
<context:include-filter>子节点表示要包含的目标类,需要将<context:component-scan>的use-default-filters属性的值设置为false.
<context:exclude-filter>子节点表示要排除在外的目标类
<context:component-scan>下可以拥有若干个<context:include-filter>和<context:exclude-filter>子节点
使用注解装配Bean与Bean之间的关联关系(组件装配):
<context:component-scan>元素会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可以自动装配具有@Autowired和@Resource、@Inject注解的属性
如:
Autowire
Autowire
测试结果:
result
@AutoWired自动装具有兼容类型的单个Bean属性:
构造器,普通字段(即使非public),一切具有参数的方法都可以应用@Autowired注解
默认情况下,所有使用@Autowired注解的属性都需要被设置,当Spring找不带匹配的Bean装配属性时,会抛出异常,若某一属性允许不被设置,可以设置@Autowired注解的required属性为false.
@Resource注解要求一个Bean名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为Bean的名称
9、Spring AOP:
AOP(Aspect-Oriented-Programming)
解决日志以及代码的混乱问题
AOP:面向切面编程,是一种新的方法论,是对传统的OOP的补充
AOP的主要编程对象是切面,而切面模块化切关注点
AOP的优点:
每个事物逻辑位于一个位置,代码不分散,便于维护和升级
业务模块更简洁,只包含核心业务代码
动态代理的方式处理日志:
被代理对象:
Object
被代理对象实现类:
Object implement class
代理类:
Proxy class
测试类:
Test class
AOP分析:

AOP关键词:
切面(Aspect):横切关注点被模块化的特殊对象
通知(Advice):切面必须要完成的工作
目标(Target):被通知的对象
代理(Proxy):向目标对象应用通知之后创建的对象
连接点(Joinpoint):程序执行的某个特定位置,如某个方法调用前、调用后、抛出异常等
切点(pointcut):每个类都拥有多个连接点。AOP通过切点定位到特定的连接点,一个切点可对应多个连接点
AspectJ(Spring2.0以上)为Java社区中最完整最流行的AOP框架,配置方式有以下两种:
基于注解
基于XML
基于注解AspectJ注解支持:
必须在classpath下包含AspectJ类库: aopalliance.jar、aspectj.weaver.jar、spring-aspects.jar
将aop Schema添加到<beans>根元素中
要在Spring IOC容器中启用AspectJ注解支持,只要在Bean配置文件中定义一个空的XML元素<aop:aspectj-autoproxy>
必须要在Bean配置文件中配置需要的Bean,通过<context:component-scan/>元素
当Spring IOC容器侦测到Bean配置文件中的<aop:aspectj-autoproxy>元素时,会自动为与AspectJ切面匹配的Bean创建代理
使用注解声明一个切面需要两步:
把相应的类加到IOC容器中
声明该类为一个切面
声明执行的位置
在配置文件中加入:

<
aop:aspectj-autoproxy

</
aop:aspectj-autoproxy

如:
结构:

structure
注解:
annotation
配置:
configuration
测试结果:
Test result
在AspectJ注解中,切面只是一个带有@Aspect注解的Java类
通知就是标注有某种注解的简单的Java方法
AspectJ支持5种类型的通知注解:
@Before:前置通知,在方法执行之前执行
annotation
@After:后置通知,在方法执行之后执行,无论是否发生异常都会执行
annotation
@AfterRunning:返回通知,在方法返回结果之后执行
annotation
@AfterThrowing:异常通知,在方法抛出异常之后会执行
annotation
@Around:环绕通知,围绕着方法执行
切面优先级的指定:
通过加入注解@Order(number), number值越小,优先级越高

重用切入点表达式:
通过定义一个声明的方法

对于非当前类的其他类中的方法,可以使用如下形式:(包名+类名+方法名)

基于XML配置文件的方式来配置AOP:
结构:

切面类:

配置文件:

测试结果:

10、Spring对JDBC的支持:
使用JdbcTemplate更新数据库
用sql语句和参数更新数据库(update)
public int update(String sql, Object ... args) throw DataAccessException
批量更新数据库(batchUpdate)
public int[] batchUpdate(String sql, List<Object[]> batchArgs)
查询多行(query)
public <T> List<T> query(String sql, ParameterizedRowMapper<T> rm, Object... args)throws DataAccessException
单值查询(queryForObject)
public <T> T queryForObject(String sql, Class<T> requiredType, Object... args) throw DataAccessException
配置文件获取数据库连接信息:
结构:

springContext.xml

<context:property-placeholder location ="classpath:db.properties" />

<bean id ="dataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource">
<property name = "user" value = "${user}"></property>
<property name = "password" value = "${password}"></property>
<property name = "driverClass" value = "${driverClass}"></property>
<property name = "jdbcUrl" value = "${jdbcUrl}"></property>
<property name = "maxPoolSize" value = "${maxPoolSize}" ></property>
<property name = "initialPoolSize" value = "${initialPoolSize}"></property>
</bean>
db.properties:
user = root
password = java
driverClass = com.mysql.jdbc.Driver
jdbcUrl = jdbc:mysql://localhost:3306/spring
maxPoolSize = 10
initialPoolSize = 5
JdbcTemplate的配置:
配置信息:

<bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate">
<property name = "dataSource" ref = "dataSource" ></property>
</bean>
测试结果:

JdbcTemplate的单批更新插入与批量插入:
方法:

测试结果:

JdbcTemplate的查询:(queryForObject、queryForList用于获取某一列的值)
方法:

测试结果:

JdbcTemplate不支持级联属性
JdbcTemplate是线程安全的,故可以在IOC容器中声明它的单个实例,并将这个实例注入到所有的DAO实例中,如:
DAO类:

配置DAO依赖注入JdbcTemplate:

测试结果:

spring JDBC框架还提供了一个JdbcDaoSupport类来简化DAO实现,该类声明了jdbcTemplate属性,它可以从IOC容器中注入.或者从数据源中创建
Spring使用NamedParameterJdbcTemplate
经典JDBC中,SQL参数使用占位符(?)表示
在Spring JDBC框架中,绑定SQL参数的另一种方式是使用具名参数(named parameter),也即是绑定变量(bind variable)
具名参数只在NamedParameterJdbcTemplate中得到支持
配置形式:

<
bean
id
=
"namedParameterJdbcTemplate"
class
=
"org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"

<
constructor-arg
ref
=
"jdbcTemplate"

</
constructor-arg
<--
NamedParameterJdbcTemplate没有无参构造器,必须提供参数-->

</
bean

如:



使用具名参数可以传递对象进行操作,如:



11、Spring事物管理
用于确保数据的完整性与一致性

事物的四个关键属性(ACID)
原子性(automicity)
一致性(consistency)
隔离性(isolation)
持久性(durability)
Spring中的事物管理:
Spring既支持编程式事物管理,也支持声明式事物管理
编程式事物管理:将事物管理代码嵌入到业务方法中来控制事物的提交和回滚
声明式事物管理:将事物管理代码从业务方法中分离出来,以声明的方式来实现事物管理,可以通过AOP方法模块化,Spring通过Spring AOP框架支持声明式事物管理
Spring的核心事物管理抽象是Interface PlatformTransactionManager,管理封装了一组独立于技术的方法
Spring中的事物管理器的不同实现:
Class DataSourceTransactionManager:在应用程序中只需要处理一个数据源,且通过JDBC存取
Class JtaTransactionManager:在JavaEE应用服务器上用JTA(Java Transaction API)进行管理
Class HibernateTransactionManager:用Hibernate框架存取数据库
...
事物管理器以普通的Bean形式声明在Spring IOC容器中
声明式事物:
配置事物管理器:

<
bean
id
=
"dataSourceTransactionManager"
class
=
"org.springframework.jdbc.datasource.DataSourceTransactionManager"

<
property
name
=
"dataSource"
ref
=
"dataSource"

</
property

</
bean

<
tx:annotation-driven
transaction-manager
=
"dataSourceTransactionManager"
/>
事物注解,使用@Transactional,如:


Spring事物的传播行为:
当事物方法被另一个事物方法调用时,必须指定事物应该如何传播
事物的传播行为可以由传播属性指定
Spring支持的事物传播行为:
REQUIRED(默认的传播行为,即使用调用方法的事物)
REQUIRED_NEW
SUPPORTS
NOT_SUPPORTED
MANDATORY
NEVER
NESTED
使用propagation指定传播行为,如:
@Transactional
(propagation=Propagation.REQUIRED)
Spring通过注解设置事物隔离级别、回滚、只读、过期:
使用isolation指定事物的隔离级别
回滚:默认情况下,Spring的声明式事物对所有的运行时异常进行回滚,可以通过以下属性设置,一般不做设置:
noRollbackFor
rollbackFor
rollbackForClassName
只读属性通过readOnly设置,取值为true或false,表示这个事物只读取数据但不更新数据,这样可以帮助数据库引擎优化事物
过期(超时),使用timeout指定强制回滚之前事物可以占用的时间,单位为秒(S),如ATM机的取款倒计时
如:

Spring通过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"
xmlns:context = "http://www.springframework.org/schema/context"
xmlns:tx = "http://www.springframework.org/schema/tx"
xmlns:aop = "http://www.springframework.org/schema/aop"
xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">


<context:property-placeholder location = "classpath:db.properties"/>

<bean id = "dataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource">
<property name = "user" value = "${user}" ></property>
<property name = "password" value = "${password}"></property>
<property name = "driverClass" value = "${driverClass}"></property>
<property name = "jdbcUrl" value = "${jdbcUrl}" ></property>
<property name = "maxPoolSize" value = "${maxPoolSize}"></property>
<property name = "initialPoolSize" value = "${initialPoolSize}"></property>
</bean>

<bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate">
<property name = "dataSource" ref = "dataSource" ></property>
</bean>

<bean id = "namedParameterJdbcTemplate" class = "org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref = "jdbcTemplate" ></constructor-arg>
</bean>

<bean id = "dataSourceTransactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name = "dataSource" ref = "dataSource"></property>
</bean>

<bean id = "bookShopDAO" class = "com.djh.spring.transaction.BookShopDaoImp">
<property name = "jdbcTemplate" ref = "jdbcTemplate"></property>
</bean>
<bean id = "bookShopService" class = "com.djh.spring.transaction.BookShopServiceImp">
<property name = "bookShopDao" ref = "bookShopDAO" ></property>
</bean>

<tx:advice id = "txAdvice" transaction-manager = "dataSourceTransactionManager">
<tx:attributes>

<tx:method name = "service" propagation = "REQUIRES_NEW" />
<tx:method name = "" />
</tx:attributes>
</tx:advice>

<aop:config>
<aop:pointcut expression = "execution(
com.djh.spring.transaction.BookShopDao.*(..))" id = "txPointCut" />
<aop:advisor advice-ref = "txAdvice" pointcut-ref = "txPointCut"/>
</aop:config>

</beans>

相关文章

  • 开发常用插件

    前言 开发所需常用插件,随笔 Android - Android studio Spring boot - ide...

  • 2018-08-23

    Java学习随笔——Spring IOC的原理 Java开发的人一般都使用过spring框架,其最大的特点就是IO...

  • 使用jasypt对SpringBoot配置文件进行加密

    参考:工作随笔——jasypt-spring-boot使用[https://www.cnblogs.com/zz0...

  • Spring随笔

    1、Spring简介:Spring是一个IOC(DI)和AOP容器框架轻量级:Spring是非侵入性的,基于开发的...

  • Spring 随笔

    1.Spring JPA 条件查询 ``` @Override public ListgetJobsByAccou...

  • Spring boot 随笔

    备忘知识点: Java Class Loder: https://www.ibm.com/developerwor...

  • Spring课堂随笔

    1.切入点:所谓切入点就是真正被拦截到的点。 2.织入=增强+目标对象的过程,一个类被AOP 织入增强后,产生一个...

  • 蒙田:探讨哲学就是学习死亡

    作者蒙田,节选自《蒙田随笔全集》马振骋 / 上海书店出版社 / 2009 Spring来自慧田哲学00:0003:...

  • Java 小记 — Spring Boot 的实践与思考

    前言 本篇随笔用于记录我在学习 Java 和构建 Spring Boot 项目过程中的一些思考,包含架构、组件和部...

  • 2018-03-10 Spring常见注解

    随笔中默认的包为com.demo默认接口:Demo实现类:Demo1,Demo2 使用spring注解第一步,需要...

网友评论

    本文标题:Spring随笔

    本文链接:https://www.haomeiwen.com/subject/wvamxxtx.html