回顾:Struts与Hibernate可以做什么事?
Struts,
Mvc中控制层解决方案
可以进行请求数据自动封装、类型转换、文件上传、效验…
Hibernate,
持久层的解决方案;
可以做到,把对象保存到数据库,从数据库中取出的是对象。
Spring框架
传统的方式,对象创建都是写死的。关于对象创建细节:
1.对象数量:单例,多个
2.创建时间:
action 访问时候创建
service 启动时候创建
dao 启动时候创建
3.对象的依赖关系:service依赖 dao
spring简单来说,就是处理对象的创建的、以及对象的依赖关系!
组件/框架设计
侵入式设计:
引入了框架,对现有的类的结构有影响;即需要实现或继承某些特定类。
例如:Struts框架
非侵入式设计:
引入了框架,对现有的类结构没有影响。
例如:Hibernate框架/ Spring框架
Inversion on Control , 控制反转 IOC
对象的创建交给外部容器完成,这个就做控制反转.(一个类需要一个对象,不在本类中创建)
依赖注入, dependency injection
处理对象的依赖关系(一个类需要一个对象,拿过来的过程)
IOC/DI区别:
控制反转,解决对象创建的问题 【对象创建交给别人】
依赖注入,在创建完对象后, 对象的关系的处理就是依赖注入 【通过set方法依赖注入】
AOP
面向切面编程,切面举例:事务、日志、权限;
Spring框架:
可以解决对象创建以及对象之间依赖关系的一种框架。
且可以和其他框架一起使用;Spring与Struts, Spring与hibernate
(起到整合(粘合)作用的一个框架)
Spring提供了一站式解决方案:
1) Spring Core spring的核心功能: IOC容器, 解决对象创建及依赖关系2) Spring Web Spring对web模块的支持。可以与struts整合,让struts的action创建交给springspring mvc模式3) Spring DAO Spring 对jdbc操作的支持 【JdbcTemplate模板工具类】4) Spring ORM spring对orm的支持:
既可以与hibernate整合,【session】
也可以使用spring的对hibernate操作的封装5)Spring AOP 切面编程6)SpringEE spring 对javaEE其他模块的支持
spring各个版本中:
在3.0以下的版本,源码有spring中相关的所有包【spring功能 +依赖包】 如2.5版本;
在3.0以上的版本,源码中只有spring的核心功能包【没有依赖包】
(如果要用依赖包,需要单独下载!)
开发步骤:
1) 源码, jar文件:spring-framework-3.2.5.RELEASE
commons-logging-1.1.3.jar 日志
spring-beans-3.2.5.RELEASE.jar bean节点
spring-context-3.2.5.RELEASE.jar spring上下文节点
spring-core-3.2.5.RELEASE.jar spring核心功能
spring-expression-3.2.5.RELEASE.jar spring表达式相关表
以上是必须引入的5个jar文件,在项目中可以用户库管理!
2) 核心配置文件: applicationContext.xml
Spring配置文件命名方式:
applicationContext.xml / bean.xml
配置约束可以参考文档:spring-framework-3.2.5.RELEASE\docs\spring-framework-reference\htmlsingle\index.html
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.xsd">
View Code
实例:
applicationContext.xml(有时候创建的对象称bean对象是因为spring都是通过配置bean标签来得到对象)
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.xsd">
测试类:
public classTest {//1. 通过工厂类得到IOC容器创建的对象
@Testpublic void testIOC() throwsException {//创建对象//User user = new User();//现在,把对象的创建交给spring的IOC容器
Resource resource = new ClassPathResource("cn/itcast/a_hello/applicationContext.xml");//创建容器对象(Bean的工厂), IOC容器 = 工厂类 + applicationContext.xml
BeanFactory factory = newXmlBeanFactory(resource);//得到容器创建的对象
User user = (User) factory.getBean("user");
System.out.println(user.getId());
}//2. (方便)直接得到IOC容器对象
@Testpublic void testAc() throwsException {//得到IOC容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/a_hello/applicationContext.xml");//从容器中获取bean
User user = (User) ac.getBean("user");
System.out.println(user);
}}
spring控制对象创建的细节
applicationContext.xml配置参数的作用:
1) 对象创建数量: 单例/多例scope="singleton", 默认值, 即 默认是单例 【service/dao/工具类】scope="prototype", 多例; 【Action对象】2) 什么时候创建?
scope="prototype"在用到对象的时候,才创建对象。scope="singleton"在启动(容器初始化), 就已经创建了bean,且整个应用只有一个。(单例想延迟初始化可以配置lazy-init=true)3)是否延迟创建(该属性只是针对单例) lazy-init="false"(可不写)默认, 不延迟创建,即在启动时候就创建对象 lazy-init="true"延迟初始化, 在用到对象的时候才创建对象(只对单例有效)4) 创建对象之后,指定对象初始化/销毁时调用的方法。 init-method="init_user"【对应对象的init_user方法,在对象创建之后执行 】 destroy-method="destroy_user" 【在调用容器对象的destriy方法时候执行,(容器用实现类ClassPathXmlApplicationContext】
实例:
public classUser {private intid;privateString name;publicUser() {super();
System.out.println("------User对象创建------");
}public intgetId() {returnid;
}public void setId(intid) {this.id =id;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}public voidinit_user() {
System.out.println("创建对象之后,初始化");
}public voiddestroy_user() {
System.out.println("IOC容器销毁,user对象回收!");
}
配置:
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.xsd">
测试类:
public void testIOC() throwsException {//得到IOC容器对象 【用实现类,因为要调用销毁的方法】
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/a_hello/applicationContext.xml");
System.out.println("-----容器创建-----");//从容器中获取bean
User user1 = (User) ac.getBean("user");
User user2= (User) ac.getBean("user");
System.out.println(user1);
System.out.println(user2);//销毁容器对象 (ClassPathXmlApplicationContext类才有销毁方法)
ac.destroy();
}
spring实现创建对象的方式:
SpringIOC容器,是spring核心内容。
作用: 创建对象 & 处理对象的依赖关系
IOC容器创建对象: 有几种方式:
1) 调用无参数构造器
2) 带参数构造器
3) 工厂创建对象
工厂类,静态方法创建对象
工厂类,非静态方法创建对象
实例:
User.java
public classUser {private intid;privateString name;publicUser() {super();
System.out.println("------User对象创建【无参数构造器】------");
}public User(intid, String name) {
System.out.println("-----User对象创建【带参数构造器】--------");this.id =id;this.name =name;
}public intgetId() {returnid;
}public void setId(intid) {this.id =id;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}
@OverridepublicString toString() {return "User [id=" + id + ", name=" + name + "]";
}public voidinit_user() {
System.out.println("创建对象之后,初始化");
}public voiddestroy_user() {
System.out.println("IOC容器销毁,user对象回收!");
}
}
View Code
ObjectFactory.java
//工厂,创建对象
public classObjectFactory {//实例方法创建对象
publicUser getInstance() {return new User(100,"工厂:调用实例方法");
}//静态方法创建对象
public staticUser getStaticInstance() {return new User(101,"工厂:调用静态方法");
}
bean.xml(配置文件名字可以自定义,可以放在src下也可以在包下)
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.xsd">
测试类:
public void testIOC() throwsException {//创建IOC容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/b_create_obj/bean.xml");//获取容器中的对象
User user = (User) ac.getBean("user");
System.out.println(user);
}
处理对象依赖关系,Spring给对象的属性赋值【DI, 依赖注入】
(对象依赖的数据存放在属性中,属性可以是对象和基本类型,而将这些数据赋值给这些属性的过程就是依赖注入)
注入的方式有:
1) 通过构造函数2) 通过set方法给属性注入值3) p名称空间4) 自动装配(了解)5) 注解
构造函数,set属性,p名称空间的方式实例:
User.java
public classUser {private intid;privateString name;//--> 通过容器注入属性值
public void setId(intid) {this.id =id;
}// //--> 通过容器注入属性值
public voidsetName(String name) {this.name =name;
}public intgetId() {returnid;
}publicString getName() {returnname;
}
@OverridepublicString toString() {return "User [id=" + id + ", name=" + name + "]";
}publicUser() {super();
System.out.println("------User对象创建【无参数构造器】------");
}public User(intid, String name) {
System.out.println("-----User对象创建【带参数构造器】--------");this.id =id;this.name =name;
}
View Code
UserAction.java
public classUserAction {//Service: springIOC容器注入
privateUserService userService;public voidsetUserService(UserService userService) {this.userService =userService;
}publicString execute() {
userService.save();return null;
}
View Code
UserDao.java
public classUserDao {public voidsave() {
System.out.println("DB:保存用户");
}
View Code
UserService.java
public classUserService {private UserDao userDao; //= new UserDao();//IOC:对象的创建交给spring的外部容器完成
public voidsetUserDao(UserDao userDao) {this.userDao =userDao;
}public voidsave() {
userDao.save();
}
View Code
bean.xml
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.xsd">
测试类:
public classApp {//创建容器对象
private ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/c_property/bean.xml");
@Testpublic voidtestSet() {//从容器中获取
User user = (User) ac.getBean("user");
System.out.println(user);
}
@Testpublic voidtestExecuteAction() {//从容器中获取Action
UserAction userAction = (UserAction) ac.getBean("userAction");
userAction.execute();
}}
bean_p.xml(采用命名空间的标签的方式,属性对象也需要set方法):
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.xsd">
测试类:
//创建容器对象
private ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/c_property/bean_p.xml");
@Testpublic voidtestExecuteAction() {//从容器中获取Action
UserAction userAction = (UserAction) ac.getBean("userAction");
userAction.execute();
System.out.println(ac.getBean("user"));
}
自动装配方式,分为:根据名称和类型自动装配(属性对象也需要set方法)
1.根据名称自动装配:autowire="byName"(自动去IOC容器(bean.xml配置)中找与属性名同名的引用的对象,并自动注入)
也可以定义到全局, 这样就不用每个bean节点都去写autowire=”byName”
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.xsd"default-autowire="byName">根据名称自动装配(全局)
2.根据类型自动装配:autowire="byType"(必须确保依赖的类型在IOC容器中只有一个配置;否则报错)
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.xsd"default-autowire="byType">
(一般不推荐使用)Spring提供的自动装配简化配置,但是不利于后期的维护。(应该是依赖关系的可读性比较差,需要从类中确定)
测试类:
//创建容器对象
private ApplicationContext ac =
new ClassPathXmlApplicationContext("cn/itcast/d_auto/bean.xml");
@Testpublic voidtestExecuteAction() {//从容器中获取Action
UserAction userAction = (UserAction) ac.getBean("userAction");
userAction.execute();
}
View Code
注解方式,简化spring的IOC容器的配置
(注解的方式,属性对象不用提供set方法)
使用注解步骤:
1)先引入context名称空间:xmlns:context="http://www.springframework.org/schema/context"
2)开启注解扫描:
3)代码中使用注解
代码中相关的注解:Component/Resource
@Component :指定把一个对象加入IOC容器(还可以这样写@Component(‘属性名’),意思加入并且取名为xxx)
@Repository 作用同@Component; 在持久层使用(这样写,好像只是增强了可读性,层次比较清晰)
@Service 作用同@Component; 在业务逻辑层使用
@Controller 作用同@Component; 在控制层使用
@Resource :属性注入,根据类型注入(还可以这样写@Resource(name="xxx")注入名为xxx的对象)
实例:
UserAction.java
//@Component("userAction")//加入IOC容器//@Component
@Controller //控制层的组件
public classUserAction {
@ResourceprivateUserService userService;publicString execute() {
userService.save();return null;
}
}
View Code
UserDao.java(注解被注释掉了,是为测试注解和bean配置共同使用的情况)
//把当前对象加入ioc容器//@Component("userDao")//相当于bean.xml 【】//@Component//加入ioc容器的UserDao对象的引用名称, 默认与类名一样, 且第一个字母小写//@Repository//在持久层可以选择用这个注解
public classUserDao {publicUserDao(){
System.out.println("UserDao.UserDao()");
}public UserDao(intid){
System.out.println("UserDao.UserDao(int id)" +id);
}public voidsave() {
System.out.println("DB:保存用户!!!");
}
}
View Code
UserService.java
//@Component("userService")//userService加入ioc容器//@Component
@Service //表示业务逻辑层的组件
public classUserService {//@Resource//根据类型查找 【在容器中要确保该类型只有一个变量,针对的是注解和配置bean一起使用的情况,如果都是采用注解,只会一个类型加入IOC容器】
@Resource(name = "userDao")//根据名称查找
private UserDao userDao; //去容器中招UserDao类型的变量,找到后就赋值
public voidsave() {
userDao.save();
}
}
bean.xml
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.xsd">
//注释掉了userDao中注解(注解和配置bean可以互补的方式共同使用)
测试类:
//创建容器对象
private ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/e_anno2/bean.xml");
@Testpublic voidtestExecuteAction() {//从容器中获取Action
UserAction userAction = (UserAction) ac.getBean("userAction");
userAction.execute();
}
总结:
一种更加简便的依赖注入方式,那就是注解加自动装配,加入容器的对象添加注解,依赖的对象注入交给自动装配的方式注入(这样依赖的属性对象不用写注解,但需要写set方法,因为交个自动装配的方式)