Spring 学习笔记
八种基本类型+String类型的注入
配置文件:
<bean id="user" class="injection.User">
<property name="name">
<value>james</value>
</property>
<property name="id">
<value>123456</value>
</property>
<property name="password">
<value>password123</value>
</property>
<property name="phone">
<list>
<value>18357004390</value>
<value>18236888177</value>
</list>
</property>
<property name="addresses">
<set>
<value>北京</value>
<value>上海</value>
</set>
</property>
<property name="email">
<value>james@163.com</value>
</property>
<property name="product">
<map>
<entry>
<key>
<value>apple</value>
</key>
<value>5</value>
</entry>
<entry>
<key>
<value>banana</value>
</key>
<value>6</value>
</entry>
</map>
</property>
<property name="properties">
<props>
<prop key="key1">value1</prop>
<prop key="key2">value2</prop>
</props>
</property>
</bean>
自定义类型注入:
<bean id="uDAO" class="injection.UserDaoImpl"></bean>
<bean id="userService" class="injection.UserServiceImpl">
<property name="userDao">
<ref local="uDAO"/>
</property>
</bean>
如何通过spring框架为用户自定义类型赋值?
一、set方法赋值
1.创建对应的类 为成员变量提供set get方法
2.配置applicationContext.xml
<bean id="uDAO" class="injection.UserDAOImpl"></bean>
<bean id="userService" class="injection.UserServiceImpl">
<property name="userDAO">
<ref local="uDAO"/>
</property>
</bean>
3.编码 通过工厂获得userService对象
ApplicationContext
注意:List Set Map 会根据存储的对象不同注入方式有所不同
二、通过有参构造为成员变量赋值
开发步骤:
1.类 提供有参构造
2.spring配置文件
<bean id="c" class="constructor.Customer">
<constructor-arg> 顺序要相同
<value>James</value>
</constructor-arg>
<constructor-arg>
<value>25</value>
</constructor-arg>
</bean>
三、自动注入
概念:通过spring工厂自动扫描符合要求的对象为成员变量赋值
开发步骤:
<bean id="userDAO" class="xxx.UserDAOImpl"/>
<bean id="userService" class="xxx.UserServiceImpl" aotowire="byType">
</bean>
aotowire:byType Spring会在配置文件中自动扫描和UserServiceImpl成员变量
类型相同的对象 进行赋值
byName Spring会在配置文件中自动扫描id和UserServiceImpl成员变量名字相同的对象 进行赋值
自动注入的问题: 1.程序的可读性差 2.存在风险
综上所述:自动注入不建议使用
IOC ----- inverse of control 翻转控制
概念:把由代码来控制成员变量的赋值 翻转到了配置文件中完成
好处:解耦合
原理:Spring的工厂 工厂设计模式
DI ------- dependency injection 依赖注入
概念:当需要一个对象时,就可以等同于依赖它,那么久可以把这个对象作为成员变量
,通过spring的配置文件进行注入。
FactoryBean
概念:创建复杂对象(没有构造方法的对象)
FactoryBean开发步骤:
1、实现接口 FactoryBean
书写创建复杂对象的代码,并把所创建的复杂对象作为方法的返回值返回。
public Object getObject(){
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
return sf;
}
返回所创建的复杂对象的class类型
public Class getObjectType(){
return sf
}
2、配置文件
注意:如果在spring的配置文件中,配置的class类型是FactoryBean接口
的实现类,通过id获得的是它所创建的复杂对象。
Spring+Hibernate 整合
搭建开发环境
1、jar
2、配置文件 applicationContext.xml hibernate.cfg.xml xxx.hbm.xml
3、预先配置(初始化) struts2 web.xml Filter hibernate hibernate.cfg.xml配置参数
Spring+hibernate 整合思想
hibernate ----DAO
spring ------创建对象 依赖注入
如何限定简单对象的创建次数?
<bean id="u" class="xxx.User" scope="singleton/prototype"/>
scope: singleton 只会创建一次对象 默认值
prototype 每次都会创建一个新对象
Spring高级特性:
1、生命周期
什么是生命周期?
概念:spring工厂所创建的对象 什么时候创建 什么时候运行 什么时候销毁
什么时候创建对象-----当spring工厂被创建时会自动把配置文件中所有的对象都创建出来
节省创建对象的延损 提高效率
什么时候活着--------工厂活着 对象就活着
什么时候销毁对象-----工厂关闭,对象销毁(必须调用工厂的close方法 以为工厂关闭)
spring相关的生命周期方法:
初始化方法(名字随便): spring会在创建一个对象之后 自动的调用初始化方法
销毁方法(名字随便):spring会在销毁一个对象之前 自动的调用销毁方法
<bean id="c" class="life.Customer" init-method="myInit" destroy-method="myDestroy"/>s
2、PropertyPlaceholderConfigure(配置信息参数化)
概念:把spring配置文件中 那些需要经常修改的字符串信息从spring的配置文件中
转移到一个小的配置文件中。
PropertyPlaceholderConfigure开发步骤:
1.准备小配置文件
放置位置---src下随便
properties结尾
2.进行spring配置文件与小配置文件的整合
<context property-placeholder location="classpath:/propertyplace/jdbc.properties"/>
3.在spring经常需要修改的字符串所在位置${key}从小配置文件取值
<context:property-placeholder location="classpath:/propertyplace/jdbc.properties"/>
<bean id="conn" class="propertyplace.ConnectionFactoryBean">
<property name="driver" value="${driver}"></property>
<property name="url" value="url"></property>
<property name="username" value="username"></property>
<property name="password" value="${password}"></property>
</bean>
3.CustomEditor(自定义类型转换器)
类型转换器:spring提供的一种类,负责把配置文件中的字符串数据转换成成员变量对应的类型
自定义类型转换器:spring框架内部没有提供特殊类型的类型转换器,程序员需要自己
开发对应的类型转换器。
自定义类型转换器的开发步骤:
1、类 implements PropertyEditor
extends PropertyEditorSupport
1 获得spring配置文件中的字符串数据
2 进行字符串数据的转换
3 为成员变量进行注入
2.配置文件
1 声明:告知spring类的存在
2 注册:告知spring这个类型应用于哪种类型的转换
org.springfremeword.beans.factory.config.CustomEditorConfigure
用于类型转换的注册
public class DateConverter extends PropertyEditorSupport {
/**
* 1 获得spring配置文件中的字符串数据 text参数---<value>2016-7-13</value>
* 2 进行String ---Date转换
* 3 进行赋值
*/
@Override
public void setAsText(String text){
try {
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
Date d = sd.parse(text);
//赋值 把转换好的Date交给spring赋值给date
setValue(d);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
配置文件:
<bean id="user" class="CustomEditor.User">
<property name="name" value="james"></property>
<property name="age" value="25"></property>
<property name="date">
<value>2016-7-13</value>
</property>
</bean>
<bean id="dateConverter" class="CustomEditor.DateConverter"></bean>
<bean id="customEditor" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry>
<key>
<value>java.util.Date</value>
</key>
<ref local="dateConverter"></ref>
</entry>
</map>
</property>
</bean>
spring类型转换器的工作原理:
1 发现Date日期转换 没有提供系统的类型转换器
2 注册
<bean id="customEditor" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry>
<key>
<value>java.util.Date</value>
</key>
<ref local="dateConverter"></ref>
</entry>
</map>
</property>
</bean>
3 调用DateConverter DateConverter implements PropertyEditor setAsText();
4 setValue(d); 交给spring为date赋值
AOP编程(Aspect oriented programming) 面向切面编程
核心:代理设计模式 Proxy
概念:通过代理类 为原始的service增加额外功能
好处:因为引入代理类,原始service不再书写额外功能,被修改的几率大大减小,
提高程序的维护性
代理类开发要素:代理类=原始的service+额外功能+实现相同的接口
静态代理设计模式:一个原始类对应一个世纪存在的代理类
静态代理设计模式的弊端:
1 不利于项目的管理 维护
2 额外功能的代码冗余
3 额外功能不好维护
动态代理
spring动态代理设计模式概念:
spring框架通过引入动态代理机制 解决了静态代理中的问题 本质上没有区别
spring动态代理的开发思路:
1 原始类 没有额外功能的service 只负责业务 DAO调用
2 额外的功能 Advice接口
MethodBeforeAdvice 额外功能运行在原始方法运行之前执行
AfterReturningAdvice 额外功能运行在原始方法运行之后执行
MethodInterceptor 额外功能运行在原始方法运行之前 之后执行
ThrowsAdvice 额外功能运行在原始方法出现异常时执行
3 切入点 切入点决定额外功能加入的位置(决定哪个原始方法加入额外功能)
<aop:config>
<!-- 所有方法都加入额外功能 -->
<aop:pointcut expression="execution(* *(..))" id="pc"/>
<aop:advisor advice-ref="before" pointcut-ref="pc"/>
</aop:config>
4 组装 额外功能+切入点 整合
<aop:advisor advice-ref="before" pointcut-ref="pc"/>
编码:
ApplicationContext ctx = new ClassPathXmlApplicationContext("xxx.xxx.xml");
UserService us = (UserService)ctx.getBean("原始对象的id值获得代理对象")
切入点 (PointCut)决定额外功能加入的位置
1 expression="execution(切入点表达式)"
2 切入点表达式
* *(..) 所有的方法都加入额外功能(不关心方法属于哪个类)
* *(..) ---- public void add(int a,int b);
---- public void add (int a,int b)
对login方法加入额外功能 * login(..)
其他--- * login(Stiring,..)
参数类型不是java.lang包里的类型 --- 如 * register(dynamic.User)
以类作为切入点
* *.UserService.*(..) ------UserService类中的所有方法
public int 包.类.方法(参数)
以包为切入点同理
注意: * dynamicproxy.*.*(..) 当前包
* dynamicproxy..*.*(..) ..表示当前包及其子包
复合切入点 and or not
execution(* login(..)) or execution(* showOrder(..))
AOP编程 Aspect Oriented Programming 面向切面编程
OOP 面向对象编程: 以对象为基本单位的程序开发
C 面向过程编程: 以过程(函数)为基本单位的程序开发
AOP 面向切面编程: 以切面(切入点+额外功能)为基本单位的程序开发
概念:本质上就是Spring动态代理的开发,通过代理类为原始类增加额外的功能 利于维护
好处:利于维护
原理:代理设计模式
研究Spring动态代理(AOP)
1 spring框架如何在程序运行的过程中动态的创建代理类?
JDK Proxy newProxyInstance();方法的作用:可以保证在运行过程中为原始类创建代理
类加载器:类加载器负责把一个.class文件读入JVM 类加载器的来源 .class文件
2 为什么在spring工厂中 通过原始对象的id而获得代理对象?
基于BeanPostProcessor机制
Spring框架提供了JdbcTemplate封装jdbc开发中冗余代码
1、JdbcTemplate用在哪
DAO层
2、JdbcTemplate怎么使用
JdbcTemplate进行CRUD
jdbcTemplate进行CUD(增删改)
jdbcTemplate.update(String sql,Object[] args)
例如:
jdbcTemplate.update("insert into t_user(name,password")
value(?,?),new Object[]{"james","123456"}
jdbcTemplate进行R(查询)
单行结果的查询 封装一个对象
Object ret = jdbcTempalte.queryForObject(String sql,
Object[] args,RowMapper rowMapper)
多行结果查询 封装成List<对象>
List<Object> ret = jdbcTemplate.query(String sql,Object[] args,
RowMapper rowMapper)
JdbcTemplate开发步骤
1 编码
DAO{
private JdbcTemplate jdbcTemplate;
set
get
jdbcTemplate.update();
}
2 配置
DataSource
JdbcTemplate
DAO
Spring中如何控制事务
核心思想:通过动态代理(AOP)为业务层增加事务这种额外功能
1 原始对象
2 额外功能
1 控制事务的代码
org.springframework.jdbc.datasource.DataSourceTransactionManager
注入DataSource连接池
2 事务属性
隔离属性(isolation)
概念:描述事务解决并发问题的能力
并发:多个用户同一时间访问了同一个数据
并发问题:
1 脏读 ISOLATION_READ_COMMITED 默认值
一个用户读取了另一个用户没有提交的数据,产生数据不一致
2 不可重复读 ISOLATION_REPEATABLE_READ(数据库加行级锁)
一个事务中对相同的数据进行多次查询 而查询结果不一致
3 幻影读 ISOLATION_SERIALAZABLE (数据库加表级锁)
一个事务中对相同数据进行统计 但是统计的结果不一致
传播属性
概念:描述事务解决嵌套问题的能力
PROPATATION_REQUIRED:如果外部没有事务,开启新事务 适合增删改 默认值
如果外部存在事务,融合到外部事务中
PROPAGATION_SUPPORTS:如果外部没有事务,不开启事务 适合查询
如果外部存在事务,融合到外部的事务总
只读属性 raad-only
如果本次业务为查询业务 指定只读属性 提高查询效率 值为true false
超时属性 timeout 默认值为-1
如果存在别的事务为当前访问的数据加锁,通过timeout属性指定最多等待多少秒
异常属性
spring默认对RuntimeException及其子类 回滚策略
Exception 及其子类 提交策略
概念:通过异常属性 改变spring在事务处理中 对异常采取默认策略
rollback-for="异常的全限定名" no-rollback-for="异常的全限定名"
3 切入点
4 切面 整合
Spring DAO层对Hibernate技术的支持(官方版本spring+hibernate整合)
org.springframework.orm.hibernate3.HibernateTemplate 替换原有的Sessin对象
hibernateTemplate:提供很多和Session方法名及作用一直的方法
结论:hibernateTemplate封装了原始的Hibernate中的Session对象
目的:在原有Session功能的基础之上,进行扩展,进行增强
public class HibernateTemplate{
private Session session;
public void save(){
session.save();
}
}
Spring+Hibernate官方版本 整合开发步骤:
1 HibernateTemplate封装session同时自动把session绑定到线程(自动调用
getCurrentSession)
2 HibernateTemplate自动在DAO开启小的事务
3 简化HQL开发
List l = hibernateTemplate.find(String sql,Object[] args);
String sql:from User as u where u.name=?
Object[] args:new Object[]{"james
注意:find只会返回List集合
4 HibernateTemplate.execute() 方法
救命用的:在某些特定的场景下,hibernateTemplate提供的方法解决不了
对应的问题,那么就需要使用execute()方法解决
public class MyHibernateCallback implements HibernateCallback{
public Object doInHibernate(Session session){
Query query = session.createQuery("from User as u where u.name=?");
query.setString(0,"james");
return query.uniqueResult();
}
}
分页操作
Query query = session.createQuery();
query.setFirstResult((pageIndex-1)*3;
query.setMaxResults(3);
query.list();
public List<User> queryUsersByPage(final int pageIndex){
List<User> users = hibernateTemplate.execute(new HibernateCallback(){
@Override
public Object doInHibernate(Session session)
throws HibernateException,SQLException{
Query query = session.createQuery();
query.setFirstResult((pageIndex-1)*3;
query.setMaxResults(3);
return query.list();
}
})
return users;
}
Spring+Struts2整合思路:
Action依赖Service 需要通过spring注入service
UserAction implements Action{
private Service;
set get
public String execute(){
}
}
Struts2+Spring整合开发步骤
准备:搭建开发环境
1 jar struts2-spring-plugin.jar
2 配置
3 预先配置
1 创建service
2 开发Struts2的Action
1 implements Action
extends ActionSupport
2 配置struts.xml
3 创建工厂
ApplicationContext ctx = new WebApplicationContext("applicationContext.xml");
org.springframework.web.context.ContextLoaderListener
作用:封装了创建工厂的代码WebApplicationContext
使用:直接在web.xml进行配置即可
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
SSH整合
Spring学习笔记
最新推荐文章于 2024-07-08 16:53:33 发布