课程内容
1. 面向接口(抽象)编程的概念与好处
2. IOC/DI的概念与好处
a) inversion of control
b) dependency injection
3. AOP的概念与好处
4. Spring简介
5. Spring应用IOC/DI(重要)
a) xml
b) annotation
6. Spring应用AOP(重要)
a) xml
b) annotation
7. Struts2.1.6 +Spring2.5.6 + Hibernate3.3.2整合(重要)
a) opensessionInviewfilter(记住,解决什么问题,怎么解决)
8. Spring JDBC
面向接口编程(面向抽象编程)
1. 场景:用户添加
2. Spring_0100_AbstractOrientedProgramming
a) 不是AOP:Aspect Oriented Programming
3. 好处:灵活
什么是IOC(DI),有什么好处
1. 把自己new的东西改为由容器提供
a) 初始化具体值
b) 装配
2. 好处:灵活装配
Spring简介
1. 项目名称:Spring_0200_IOC_Introduction
2. 环境搭建
a) 只用IOC
i. spring.jar , jarkata-commons/commons-loggin.jar
3. IOC容器
a) 实例化具体bean
b) 动态装配
4. AOP支持
a) 安全检查
b) 管理transaction
Spring IOC配置与应用
1. FAQ:不给提示:
a) window – preferences – myeclipse – xml – xml catalog
b) User Specified Entries – add
i. Location: D:\share\0900_Spring\soft\spring-framework-2.5.6\dist\resources\spring-beans-2.5.xsd
ii. URI: file:///D:/share/0900_Spring/soft/spring-framework-2.5.6/dist/resources/spring-beans-2.5.xsd
iii. KeyType: Schema Location
iv. Key: http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
2. 注入类型
a) Spring_0300_IOC_Injection_Type
b) setter(重要)
c) 构造方法(可以忘记)
d) 接口注入(可以忘记)
3. id vs. name
a) Spring_0400_IOC_Id_Name
b) name可以用特殊字符
4. 简单属性的注入
a) Spring_0500_IOC_SimpleProperty
b) <property name=… value=….>
5. <bean 中的scope属性
a) Spring_0600_IOC_Bean_Scope
b) singleton 单例
c) proptotype 每次创建新的对象
6. 集合注入
a) Spring_0700_IOC_Collections
b) 很少用,不重要!参考程序
7. 自动装配
a) Spring_0800_IOC_AutoWire
b) byName
c) byType
d) 如果所有的bean都用同一种,可以使用beans的属性:default-autowire
8. 生命周期
a) Spring_0900_IOC_Life_Cycle
b) lazy-init (不重要)
c) init-method destroy-methd 不要和prototype一起用(了解)
9. Annotation第一步:
a) 修改xml文件,参考文档<context:annotation-config />
10. @Autowired
a) 默认按类型by type
b) 如果想用byName,使用@Qulifier
c) 写在private field(第三种注入形式)(不建议,破坏封装)
d) 如果写在set上,@qualifier需要写在参数上
11. @Resource(重要)
a) 加入:j2ee/common-annotations.jar
b) 默认按名称,名称找不到,按类型
c) 可以指定特定名称
d) 推荐使用
e) 不足:如果没有源码,就无法运用annotation,只能使用xml
12. @Component @Service @Controller @Repository
a) 初始化的名字默认为类名首字母小写
b) 可以指定初始化bean的名字
13. @Scope
14. @PostConstruct = init-method; @PreDestroy = destroy-method;
什么是AOP
1. 面向切面编程Aspect-Oriented-Programming
a) 是对面向对象的思维方式的有力补充
2. Spring_1400_AOP_Introduction
3. 好处:可以动态的添加和删除在切面上的逻辑而不影响原来的执行代码
a) Filter
b) Struts2的interceptor
4. 概念:
a) JoinPoint
b) PointCut
c) Aspect(切面)
d) Advice
e) Target
f) Weave
Spring AOP配置与应用
1. 两种方式:
a) 使用Annotation
b) 使用xml
2. Annotation
a) 加上对应的xsd文件spring-aop.xsd
b) beans.xml <aop:aspectj-autoproxy />
c) 此时就可以解析对应的Annotation了
d) 建立我们的拦截类
e) 用@Aspect注解这个类
f) 建立处理方法
g) 用@Before来注解方法
h) 写明白切入点(execution …….)
i) 让spring对我们的拦截器类进行管理@Component
3. 常见的Annotation:
a) @Pointcut
b) @Before
c) @AfterReturning
d) @AfterThrowing
e) @After
f) @Around
4. 织入点语法
a) void !void
b) 参考文档(* ..)
5. xml配置AOP
a) 把interceptor对象初始化
b) <aop:config
i. <aop:aspect …..
1. <aop:pointcut
2. <aop:before
Spring整合Hibernate
1. Spring 指定datasource
a) 参考文档,找dbcp.BasicDataSource
i. c3p0
ii. dbcp
iii. proxool
b) 在DAO或者Service中注入dataSource
c) 在Spring中可以使用PropertyPlaceHolderConfigure来读取Properties文件的内容
2. Spring整合Hibernate
a) <bean .. AnnotationSessionFactoryBean>
i. <property dataSource
ii. <annotatedClasses
b) 引入hibernate 系列jar包
c) User上加Annotation
d) UserDAO或者UserServie 注入SessionFactory
e) jar包问题一个一个解决
3. 声明式的事务管理
a) 事务加在DAO层还是Service层?
b) annotation
i. 加入annotation.xsd
ii. 加入txManager bean
iii. <tx:annotation-driven
iv. 在需要事务的方法上加:@Transactional
v. 需要注意,使用SessionFactory.getCurrentSession不要使用OpenSession
c) @Transactional详解
i. 什么时候rollback
1. 运行期异常,非运行期异常不会触发rollback
2. 必须uncheck (没有catch)
3. 不管什么异常,只要你catch了,spring就会放弃管理
4. 事务传播特性:propagation_required
5. read_only
d) xml(推荐,可以同时配置好多方法)
i. <bean txmanager
ii. <aop:config
1. <aop:pointcut
2. <aop:advisor pointcut-ref advice-ref
iii. <tx:advice: idtransaction-manager =
e) HibernateTemplate、HibernateCallback、HibernateDaoSupport(不重要)介绍
i. 设计模式:TemplateMethod
ii. Callback:回调/钩子函数
iii. 第一种:(建议)
1. 在spring中初始化HibernateTemplate,注入sessionFactory
2. DAO里注入HibernateTemplate
3. save写getHibernateTemplate.save();
iv. 第二种:
1. 从HibernateDaoSupport继承
2. 必须写在xml文件中,无法使用Annotation,因为set方法在父类中,而且是final的
f) spring整合hibernate的时候使用packagesToScan属性,可以让spring自动扫描对应包下面的实体类
Struts2.1.6 +Spring2.5.6 + Hibernate3.3.2
1. 需要的jar包列表
jar包名称 | 所在位置 | 说明 |
antlr-2.7.6.jar | hibernate/lib/required | 解析HQL |
aspectjrt | spring/lib/aspectj | AOP |
aspectjweaver | .. | AOP |
cglib-nodep-2.1_3.jar | spring/lib/cglib | 代理,二进制增强 |
common-annotations.jar | spring/lib/j2ee | @Resource |
commons-collections-3.1.jar | hibernate/lib/required | 集合框架 |
commons-fileupload-1.2.1.jar | struts/lib | struts |
commons-io-1.3.2 | struts/lib | struts |
commons-logging-1.1.1 | 单独下载,删除1.0.4(struts/lib) | struts spring |
dom4j-1.6.1.jar | hibernate/required | 解析xml |
ejb3-persistence | hibernate-annotation/lib | @Entity |
freemarker-2.3.13 | struts/lib | struts |
hibernate3.jar | hibernate |
|
hibernate-annotations | hibernate-annotation/ |
|
hibernate-common-annotations | hibernate-annotation/lib |
|
javassist-3.9.0.GA.jar | hiberante/lib/required | hibernate |
jta-1.1.jar | .. | hibernate transaction |
junit4.5 |
|
|
mysql- |
|
|
ognl-2.6.11.jar | struts/lib |
|
slf4j-api-1.5.8.jar | hibernate/lib/required | hibernate-log |
slf4j-nop-1.5.8.jar | hibernate/lib/required |
|
spring.jar | spring/dist |
|
struts2-core-2.1.6.jar | struts/lib |
|
xwork-2.1.2.jar | struts/lib | struts2 |
commons-dbcp | spring/lib/jarkata-commons |
|
commons-pool.jar | .. |
|
struts2-spring-plugin-2.1.6.jar | struts/lib |
|
2. BestPractice:
a) 将这些所有的jar包保存到一个位置,使用的时候直接copy
3. 步骤
a) 加入jar包
b) 首先整合Spring + Hibernate
i. 建立对应的package
1. dao / dao.impl / model / service / service.impl/ test
ii. 建立对应的接口与类框架
1. S2SH_01
iii. 建立spring的配置文件(建议自己保留一份经常使用的配置文件,以后用到的时候直接copy改)
iv. 建立数据库
v. 加入Hibernate注解
1. 在实体类上加相应注解@Entity @Id等
2. 在beans配置文件配置对应的实体类,使之受管
vi. 写dao service的实现
vii. 加入Spring注解
1. 在对应Service及DAO实现中加入@Component,让spring对其初始化
2. 在Service上加入@Transactional或者使用xml方式(此处建议后者,因为更简单)
3. 在DAO中注入sessionFactory
4. 在Service中注入DAO
5. 写DAO与Service的实现
viii. 写测试
c) 整合Struts2
i. 结合点:Struts2的Action由Spring产生
ii. 步骤:
1. 修改web.xml加入 struts的filter
2. 再加入spring的listener,这样的话,webapp一旦启动,spring容器就初始化了
3. 规划struts的action和jsp展现
4. 加入struts.xml
a) 修改配置,由spring替代struts产生Action对象
5. 修改action配置
a) 把类名改为bean对象的名称,这个时候就可以使用首字母小写了
b) @Scope(“prototype”)不要忘记
iii. struts的读常量:
1. struts-default.xml
2. struts-plugin.xml
3. struts.xml
4. struts.properties
5. web.xml
iv. 中文问题:
1. Struts2.1.8已经修正,只需要改i18n.encoding = gbk
2. 使用spring的characterencoding
3. 需要严格注意filter的顺序
4. 需要加到Struts2的filter前面
v. LazyInitializationException
1. OpenSessionInViewFilter
2. 需要严格顺序问题
3. 需要加到struts2的filter前面
____________________________________________________________________________________________________________________
Spring_0100_AbstractOrientedProgrammingspring
spring 原理模拟
package com.demo.model;
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
package com.demo.model;
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
package com.demo.dao.impl;
import com.demo.dao.UserDAO;
import com.demo.model.User;
public class UserDAOImpl implements UserDAO {
@Override
public void save(User u) {
System.out.println("user save");
}
}
package com.demo.service;
import com.demo.dao.UserDAO;
import com.demo.dao.impl.UserDAOImpl;
import com.demo.model.User;
// 面向接口或者抽象编程,需要用谁直接在service 里面new谁 实现DAO接口即可
//面向抽象编程就是 灵活
public class UserService {
private UserDAO userDAO;// = new UserDAOImpl(); 把后半部分放在beans.xml配置文件里
public UserDAO getUserDAO() {
return userDAO;
}
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
public void add(User u) {
this.userDAO.save(u);
}
}
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
public class Sample1 {
public static void main(String[] args) throws Exception {
SAXBuilder sb = new SAXBuilder();
Document doc = sb.build(Sample1.class.getClassLoader().getResourceAsStream("test.xml")); //构造文档对象
Element root = doc.getRootElement(); // 获取根元素
List list = root.getChildren("disk"); // 取名字为disk的所有元素
for(int i=0; i<list.size(); i++) {
Element element = (Element)list.get(i);
String name = element.getAttributeValue("name");
String capacity = element.getChildText("capacity");
String directoris = element.getChildText("directories");
String files = element.getChildText("files");
System.out.println("磁盘信息:");
System.out.println("分区盘符:" + name);
System.out.println("分区容量:" + capacity);
System.out.println("目录数: " +directoris);
System.out.println("文件数: " +files);
System.out.println("====================================");
}
}
}
package com.demo.spring;
public interface BeanFactory {
public Object getBean(String name);
}
package com.demo.spring;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
public class ClassPathXmlApplicationContext implements BeanFactory {
private Map<String,Object> beans = new HashMap<String, Object>();
//IOC Inverse of Control DI Dependency Injection
public ClassPathXmlApplicationContext() throws Exception {
SAXBuilder sb = new SAXBuilder();
Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml")); //构造文档
Element root = doc.getRootElement(); // 获取根元素
List list = root.getChildren("bean"); //取名字为disk 的所有元素
for (int i = 0; i < list.size(); i++) {
Element element = (Element)list.get(i);
String id=element.getAttributeValue("id");
String clazz=element.getAttributeValue("class");
Object o = Class.forName(clazz).newInstance();
System.out.println(id);
System.out.println(clazz);
beans.put(id, o);
for(Element propertyElement : (List<Element>)element.getChildren("property")) {
String name = propertyElement.getAttributeValue("name"); //userDAO
String bean = propertyElement.getAttributeValue("bean"); //u
Object beanObject = beans.get(bean); //UserDAOImpl instance
String methodName = "set" + name.substring(0,1).toUpperCase() + name.substring(1);
System.out.println("method name = " + methodName);
Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
m.invoke(o, beanObject);
}
}
}
@Override
public Object getBean(String name) {
return beans.get(name);
}
}
<beans>
<bean id="u" class="com.demo.dao.impl.UserDAOImpl"/>
<bean id="userService" class="com.demo.service.UserService">
<property name="userDAO" bean="u"/>
</bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<HD>
<disk name="C">
<capacity>8G</capacity>
<directories>200</directories>
<files>1580</files>
</disk>
<disk name="C">
<capacity>8G</capacity>
<directories>500</directories>
<files>3000</files>
</disk>
</HD>
spring api 引入方法
在spring jar包上面点右键 ---> properties ---> javadoc Location -----> file:/D:/javasoft/ssh/spring-framework-2.5.6/docs/api/
在spring里面写配置文件的时候不给提示的解决方法
a) window – preferences – myeclipse – xml – xml catalog
1. FAQ:不给提示:
a) window – preferences – myeclipse – xml – xml catalog
b) User Specified Entries – add
i. Location: D:\share\0900_Spring\soft\spring-framework-2.5.6\dist\resources\spring-beans-2.5.xsd
ii. URI: file:///D:/share/0900_Spring/soft/spring-framework-2.5.6/dist/resources/spring-beans-2.5.xsd
iii. KeyType: Schema Location
iv. Key: http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
1. 注入类型
a) Spring_0300_IOC_Injection_Type
b) setter(重要)
c) 构造方法(可以忘记)
d) 接口注入(可以忘记)
以下是setter 注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="u" class="com.demo.dao.impl.UserDAOImpl"/>
<bean id="userService" class="com.demo.service.UserService">
<property name="userDAO" ref="u"/>
</bean>
</beans>
package com.demo.service;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.demo.model.User;
// Dependency Injection 依赖注入 依赖容器注入的对象 (灵活)
// Inverse of Control 控制反转 原来具体的实现控制在自己手里,现在控制在容器手里
public class UserServiceTest {
@Test
public void testAdd() throws Exception{
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
UserService service = (UserService)ctx.getBean("userService");
User u = new User();
u.setUsername("li");
u.setPassword("ww");
service.add(u);
}
}
构造方法注入
public UserService(UserDAO userDAO) {
super();
this.userDAO = userDAO;
}
<constructor-arg>
<ref bean="u"/>
</constructor-arg>
1. id vs. name
a) Spring_0400_IOC_Id_Name
b) name可以用特殊字符
<bean name="u" class="com.demo.dao.impl.UserDAOImpl"/> 把 id 改成name 原因是可以加特殊字符 (不重要)
1. 简单属性的注入(不重要)
a) Spring_0500_IOC_SimpleProperty
b) <property name=… value=….>
<bean name="u" class="com.demo.dao.impl.UserDAOImpl">
<property name="daoId" value="9"></property>
<property name="daoStatus" value="helloworld"></property>
</bean>
1. <bean 中的scope属性
a) Spring_0600_IOC_Bean_Scope
b) singleton 单例 (默认)
c) proptotype 每次创建新的对象
UserService service = (UserService)ctx.getBean("userService");
UserService service1 = (UserService)ctx.getBean("userService");
System.out.println(service == service1);
<bean id="userService" class="com.demo.service.UserService" scope="prototype">
1. 集合注入
a) Spring_0700_IOC_Collections
b) 很少用,不重要!参考程序
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean name="userDAO" class="com.demo.dao.impl.UserDAOImpl">
<property name="sets">
<set>
<value>1</value>
<value>2</value>
</set>
</property>
<property name="lists">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
<property name="maps">
<map>
<entry key="1" value="1"></entry>
<entry key="2" value="2"></entry>
<entry key="3" value="3"></entry>
<entry key="4" value="4"></entry>
<entry key="5" value="5"></entry>
</map>
</property>
</bean>
<bean id="userService" class="com.demo.service.UserService">
<property name="userDAO" ref="userDAO"/>
</bean>
</beans>
1. 自动装配
a) Spring_0800_IOC_AutoWire
b) byName
c) byType
d) 如果所有的bean都用同一种,可以使用beans的属性:default-autowire
2. 生命周期
<bean id="userDAO1" class="com.demo.dao.impl.UserDAOImpl">
<property name="daoId" value="1"></property>
</bean>
<bean id="userDAO2" class="com.demo.dao.impl.UserDAOImpl">
<property name="daoId" value="2"></property>
</bean>
<bean id="userService" class="com.demo.service.UserService" scope="prototype" autowire="byName">
<property name="userDAO" ref="userDAO1"/>
</bean>
1. 生命周期
a) Spring_0900_IOC_Life_Cycle
b) lazy-init (不重要)
c) init-method destroy-methd 不要和prototype一起用(了解)
1. Annotation第一步:
a) 修改xml文件,参考文档<context:annotation-config />
2. @Autowired
a) 默认按类型by type
b) 如果想用byName,使用@Qulifier
c) 写在private field(第三种注入形式)(不建议,破坏封装)
d) 如果写在set上,@qualifier需要写在参数上
3. @Resource(重要)
a) 加入:j2ee/common-annotations.jar
b) 默认按名称,名称找不到,按类型
c) 可以指定特定名称
d) 推荐使用
e) 不足:如果没有源码,就无法运用annotation,只能使用xml
4. @Component @Service @Controller @Repository
a) 初始化的名字默认为类名首字母小写
b) 可以指定初始化bean的名字
5. @Scope
6. @PostConstruct = init-method; @PreDestroy = destroy-method;
Annotation-based configuration
context.xml 标签自动提示配置
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
1. Annotation第一步:
a) 修改xml文件,参考文档<context:annotation-config />
1. @Autowired
a) 默认按类型by type
b) 如果想用byName,使用@Qulifier
c) 写在private field(第三种注入形式)(不建议,破坏封装)
d) 如果写在set上,@qualifier需要写在参数上
在UserService 类里面
@Autowired //把和你参数和对应的类型的的bean注入进来 默认的是byName 用的不多,会产生各种问题
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
(@Qualifier("u") // 可以指定 匹配那个名字的Bean 注入到参数里面来
public void setUserDAO(@Qualifier("u")UserDAO userDAO) {
this.userDAO = userDAO;
}
1. @Resource(重要)
a) 加入:j2ee/common-annotations.jar
b) 默认按名称,名称找不到,按类型
c) 可以指定特定名称
d) 推荐使用
e) 不足:如果没有源码,就无法运用annotation,只能使用xml
@Resource //D:\javasoft\ssh\spring-framework-2.5.6\lib\j2ee\common-annotations.jar 包
1. @Component @Service @Controller @Repository
a) 初始化的名字默认为类名首字母小写
b) 可以指定初始化bean的名字
2. @Scope
3. @PostConstruct = init-method; @PreDestroy = destroy-method;
<context:component-scan base-package="com.demo"></context:component-scan>
package com.demo.dao.impl;
import org.springframework.stereotype.Component;
import com.demo.dao.UserDAO;
import com.demo.model.User;
@Component("u")
public class UserDAOImpl implements UserDAO {
@Override
public void save(User u) {
System.out.println("user save");
}
}
package com.demo.service;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import com.demo.dao.UserDAO;
import com.demo.dao.impl.UserDAOImpl;
import com.demo.model.User;
// 面向接口或者抽象编程,需要用谁直接在service 里面new谁 实现DAO接口即可
//面向抽象编程就是 灵活
@Component("userService")
public class UserService {
private UserDAO userDAO;
public void init() {
System.out.println("init");
}
public UserDAO getUserDAO() {
return userDAO;
}
@Resource(name="u") //常用
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
public void add(User u) {
this.userDAO.save(u);
}
public void destroy() {
System.out.println("destroy");
}
}
Spring_1300_Annotation_Pre_Post_Scope
package com.demo.service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import com.demo.dao.UserDAO;
import com.demo.dao.impl.UserDAOImpl;
import com.demo.model.User;
// 面向接口或者抽象编程,需要用谁直接在service 里面new谁 实现DAO接口即可
//面向抽象编程就是 灵活
@Component("userService")
public class UserService {
private UserDAO userDAO;
@PostConstruct //构造完成之后
public void init() {
System.out.println("init");
}
public UserDAO getUserDAO() {
return userDAO;
}
@Resource(name="u") //常用
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
public void add(User u) {
this.userDAO.save(u);
}
@PreDestroy // 对象销毁之前指定这个方法
public void destroy() {
System.out.println("destroy");
}
}