Spring && 实验IOC
一、Spring作用
1.生态体系庞大,全能型选手!【springmvc是其一个子模块,jdbcTemplate能直接操作数据库!】
2.将其他组件粘合在一起
3.IOC容器和AOP[Aspect Oreinted Programming]:
Spring的Ioc[Inverse of Controller]机制(控制反转和依赖注入)正是用在此处。
Spring的Ioc(控制反转和依赖注入)
控制反转[Ioc]:就是由容器控制程序之间的(依赖)关系,而非传统实现中,由程序代码直接操控。
控制反转是一种思想,其具体实现就是依赖注入!
依赖注入[DI:Dependency Injection]:组件之间的依赖关系由容器在运行期决定,由容器动态的将某种依赖关系注入到组件之中。
二、搭建Spring IOC容器需要的开发环境
1.导入IOC容器需要的jar包
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
commons-logging-1.1.3.jar
2.创建Spring配置文件[Spring bean Configuration File]
applicationContext.xml
三、IOC容器创建对象步骤
1.创建IOC容器对象
private ApplicationContext ioc=new FileSystemXmlApplicationContext("C:\\Users\\Administrator\\Desktop\\applicationContext.xml"); //本地文件系统(磁盘)
* private ApplicationContext ioc1=new ClassPathXmlApplicationContext("applicationContext.xml"); //src下
2.使用IOC容器在创建对象的同时,给对象的属性赋值
从IOC容器中获取对象就两种方式:1、通过id值获取bean对象
2、通过IOC容器中bean的类型获取bean对象
<!--实验1:通过IOC容器创建对象,并为属性赋值 -->
<!-- 需要由IOC容器创建对象的全类名 -->
<!-- 为了便于从IOC容器中获取book对象,声明一个一个唯一的id值 -->
<bean id="book01" class="com.neuedu.spring.bean.Book">
<property name="bookId" value="2001"></property>
<property name="bookName" value="三国演义"></property>
<property name="author" value="罗贯中"></property>
<property name="price" value="22.5"></property>
</bean>
@Test
public void test01() {
//1.创建IOC容器自身的对象
//指定配置文件以类路径为基准的配置文件名
ApplicationContext ioc= new ClassPathXmlApplicationContext("bean.xml");
//2.从IOC容器中获取指定的对象
Object bean = ioc.getBean("book01");
System.out.println(bean);
}
注意:
①IOC容器本身对象创建时,会将配置文件中配置好的bean先创建出来
②默认是单实例的,只创建bean的一个对象
③如果设置bean的scope属性为prototype,那么创建bean的对象就是多实例的,在获取的时候创建,每次获取对象都会创建新的
④.从IOC容器中获取对象
①根据bean的id获取
②根据bean的类型获取:要求容器中指定类型的bean是唯一的
bean的后置处理器:
1.指的是在bean的初始化方法前后执行操作的专门的对象。
2.自定义的后置处理器:
1)需要实现接口:org.springframework.beans.factory.config.BeanPostProcessor .
2) 做相应的配置就好!
<!-- bean的后置处理器 -->
<bean id="beanPostProcessor" class="com.neuedu.entity.MyBeanPostProcessor"></bean>
package com.neuedu.entity; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPostProcessor implements BeanPostProcessor{ @Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("===================================");
System.out.println("BeforeInitialization:"+beanName+"="+bean);
return bean;
} @Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("=============================");
System.out.println("AfterInitialization:"+beanName+"="+bean);
return bean;
} }
/*bean的后置处理器*/
@Test
public void test02() {
Object bean = ioc.getBean("beanPostProcessor");
System.out.println(bean);
}
配置FactoryBean★
public class MyFactoryBean implements FactoryBean<Book> { @Override
public Book getObject() throws Exception {
return new Book(22, "无字天书", "好啊", 22.5);
} @Override
public Class<?> getObjectType() {
return Book.class;
} @Override
public boolean isSingleton() {
return false;
} }
测试bean的作用域,分别创建单实例和多实例的bean★
<!-- scope属性为prototype,那么创建bean的对象就是多实例的 -->
<bean id="user" class="com.neuedu.entity.User" scope="prototype">
<property name="id" value="user01"/>
<property name="name" value="Danny"/>
<property name="age" value="23"/>
</bean>
<!-- scope属性为singleton为默认值,默认是单实例的,只创建bean的一个对象 -->
<bean id="user" class="com.neuedu.entity.User" scope="singleton">
<property name="id" value="user01"/>
<property name="name" value="Danny"/>
<property name="age" value="23"/>
</bean>
实验22:创建带有生命周期方法的bean
<!--创建带有生命周期方法的bean -->
<bean id="lifeObject" class="com.neuedu.entity.LifeObject" init-method="initMethod" destroy-method="destroyMethod" />
实验22[补充]:测试bean的后置处理器
①在bean的初始化方法调用前后执行操作的专门的对象
②自定义后置处理器实现该接口:org.springframework.beans.factory.config.BeanPostProcessor
③在springmvc中配置一下该bean对象.
<bean class="com.neuedu.spring.bean.Book" init-method="init"></bean>
<bean id="myBeanPostProcessor" class="com.neuedu.spring.bean.MyBeanPostProcessor"></bean>
批处理(batch)
- 批处理指的是一次操作中执行多条SQL语句
- 批处理相比于一次一次执行效率会提高很多
- 批处理主要是分两步:
1.将要执行的SQL语句保存
2.执行SQL语句
- Statement和PreparedStatement都支持批处理操作,这里我们只需要掌握PreparedStatement的批处理方式:
- 方法:
void addBatch()
- 将要执行的SQL先保存起来,先不执行
- 这个方法在设置完所有的占位符之后调用
int[] executeBatch()
- 这个方法用来执行SQL语句,这个方法会将批处理中所有SQL语句执行
- mysql默认批处理是关闭的,所以我们还需要去打开mysql的批处理:
? rewriteBatchedStatements=true
我们需要将以上的参数添加到mysql的url地址中
- 注意:低版本的mysql-jdbc驱动也不支持批处理
事务(Transaction)
- 在开发中我们的一个业务往往需要同时操作多个表,这些操作往往是不可分割,业务中的对数据库的多次操作,
要么同时成功,要么全都失败。
- 注意:我们在同一个事务中使用的数据库连接(Connection)必须是同一个。
- 事务的特性(ACID):
原子性(atomicity)
一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
一致性(consistency)
事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation)
一个事务的执行不能被其他事务干扰。
即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability)
持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久。 接下来的其他操作或故障不应该对其有任何影响。
- 操作失误的基本步骤:
1.开启事务
- 开启事务以后,我们只后的所有操作将都会在同一个事务当中
2.操作数据库
- 开启事务以后再去操作数据库,所有操作将不会直接提交到数据库中
3.提交事务
- 将修改应用到数据库
4.回滚事务
- 数据库操作过程中出现异常了,回滚事务,回滚事务以后,数据库变成开启事务之前的状态
- mysql中的事务控制
#开启事务
START TRANSACTION
#回滚事务
ROLLBACK
#提交事务
COMMIT
- JDBC中的事务主要通过Connection对象来控制的
1.开启事务
void setAutoCommit(boolean autoCommit) throws SQLException;
- 设置事务是否自动提交,默认是自动提交
- 设置事务手动提交
conn.setAutoCommit(false);
2.提交事务
void commit() throws SQLException;
- 提交事务
conn.commit()
3.回滚事务
void rollback() throws SQLException;
- 回滚事务
conn.rollback()
- 事务控制的格式:
//创建一个Connection
Connection conn = null; try{ //获取Connection
conn = JDBCUtils.getConnection(); //开启事务
conn.setAutoCommit(false); //对数据库进行操作 //操作成功,提交事务
conn.commit(); }catch(Exception e){
e.printStackTrace(); //回滚事务
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
} }finally{
JDBCUtils.close(conn, null, null);
}
数据库连接池:
6) 数据库连接池
> 数据库连接池就是存放数据库连接(Connection)的集合
> 我们获取一个数据库连接是一个相对很麻烦的过程,
如果我们获取一个数据库连接,使用一次以后就给它关闭了
下一次再去使用的时候就要重新创建一个新的数据库连接。
> 所以我们提出了一个数据库连接池的概念,数据库连接池放的都是数据库连接(Connection)
我们在去使用数据库连接时候,不用再去重新创建数据库连接,而是直接从池中获取,
使用完的数据库连接,也不是直接销毁,而是要放回到连接池。
> 数据库连接池的常见的属性:
? 初始连接数量:数据连接池创建以后,保存数据库连接的数量
? 最小空闲连接数:数据库连接池最少得未使用的数据库连接的数量
最大空闲连接数:数据库连接池最大闲置连接数,当闲置连接数满了以后,将不会有其他连接进入池
? 每次增加连接数:当数据库连接都被占用以后,一次性增加的数据库连接的个数
? 最大连接数:数据库连接池的最大容量,当最大连接数饱和了,则不再创建新的数据库连接
? 最大等待时间:当数据库连接池饱和以后,等待获取数据库连接的时间
> 常见的数据库连接池
- 所有的数据库连接池都需要实现DataSource,当使用数据库连接池是,我们便不再需要使用DriverManger获取数据库连接
而是使用DataSource。
- Connection getConnection()
- 从数据库连接池中获取数据库连接对象
1.DBCP
- DBCP是Apache出品的一款数据库连接
- DBCP依赖于commons-pool
- 使用DBCP需要导入两个jar包:
commons-dbcp-1.4.jar
commons-pool-1.5.5.jar
- 当我们通过数据库连接池获取数据库连接以后,我们所获取到数据库连接已经不是我们熟悉的那个Connection
数据库连接池对Connection对象进行了包装,它修改Connection的close()方法,
再去调用close()数据库连接将不会真的关闭,而是要放回到数据库连接池中,供其他线程使用。
- 核心类:
BasicDataSourceFactory
2.C3P0(重点)
- C3P0使用的是XML作为配置文件
- 使用c3p0需要导入一个jar包:
c3p0-0.9.1.2.jar
- 导入c3p0的配置文件:
1.配置文件的名字:c3p0-cofig.xml
2.配置文件要求放到类路径下(src)
- 核心类:
ComboPooledDataSource
- 注意:
DataSource就相当于池子,我们的数据库连接都是从DataSource中获取的,
如果程序中有多个DataSource的实例,那么我们说你还不如不用数据库连接池。
所以我们的DataSource在项目中应该只有一个实例。
实验23:引用外部属性文件★
jdbc.properties文件:
jdbc.user=root
jdbc.passowrd=123456
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.driver=com.mysql.jdbc.Driver
<context:property-placeholder location="classpath:jdbc.properties"/>
1.在目标属性上加@Value注解
@Value("${jdbc.user}")
private String username;
2.
<!-- 根据外部属性文件中的信息配置数据源 -->
<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.passowrd}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="driverClass" value="${jdbc.driver}"></property>
</bean>
ComboPooledDataSource bean = ioc.getBean(ComboPooledDataSource.class);
Connection connection = bean.getConnection();
System.out.println(connection);
Statement st = connection.createStatement();
ResultSet rs = st.executeQuery("select * from stu");
while(rs.next()){
String string = rs.getString("name");
String string2 = rs.getString("school");
System.out.println(string+"==="+string2);
}
实验24:基于XML的属性装配
①手动装配
<!-- 属性的装配:手动装配 -->
<bean id="userService" class="com.neuedu.spring.bean.UserService"></bean>
<bean id="userAction" class="com.neuedu.spring.bean.UserAction">
<property name="userService" ref="userService"></property>
</bean>
②自动装配
<!-- 1.按类型装配:byType -->
<!-- 首先检测当前bean中需要装配的属性的类型 -->
<!-- 然后在IOC容器中查找匹配这个类型的bean -->
<!-- 如果类型匹配的bean是唯一的,那么就将这个匹配的bean注入到userAction中 -->
<bean id="userService" class="com.neuedu.spring.bean.UserService"></bean>
<bean id="userAction" autowire="byType" class="com.neuedu.spring.bean.UserAction"></bean>
<!-- 2.按bean的id值装配:byName -->
<!-- 首先检测当前bean中需要装配的属性的属性名,属性名是将setXxx()方法去掉set,首字母小写得到的 -->
<!-- 然后根据属性名作为id的值,在IOC容器中查找对应的bean -->
<!-- 如果能够找到,则将找到bean注入进去 -->
6。SpEL简介【见WORLD文档---了解】
Spring Expression Language,Spring表达式语言,简称SpEL。支持运行时查询并可以操作对象图。
和JSP页面上的EL表达式、Struts2中用到的OGNL表达式一样,SpEL根据JavaBean风格的getXxx()、setXxx()方法定义的属性访问对象图,完全符合我们熟悉的操作习惯。
6.1 基本语法
SpEL使用#{…}作为定界符,所有在大框号中的字符都将被认为是SpEL表达式。
6.2 使用字面量
●整数:<property name="count" value="#{5}"/>
●小数:<property name="frequency" value="#{89.7}"/>
●科学计数法:<property name="capacity" value="#{1e4}"/>
●String类型的字面量可以使用单引号或者双引号作为字符串的定界符号
<property name=“name” value="#{'Chuck'}"/>
<property name='name' value='#{"Chuck"}'/>
●Boolean:<property name="enabled" value="#{false}"/>
实验25:[SpEL测试I]在SpEL中使用字面量
实验26:[SpEL测试II]在SpEL中引用其他bean
实验27:[SpEL测试III]在SpEL中引用其他bean的某个属性值
实验28:[SpEL测试IV]在SpEL中调用非静态方法
实验29:[SpEL测试V]在SpEL中调用静态方法
实验30:[SpEL测试VI]在SpEL中使用运算符
8.使用注解配置bean
①声明bean的注解
@Component 将当前类声明为IOC容器中的一个普通的组件
@Controller 将当前类声明为IOC容器中的一个控制器组件
@Service 将当前类声明为IOC容器中的业务逻辑层组件
@Repository 将当前类声明为IOC容器中的一个持久化层组件
Spring根据上述注解其实并不能分辨当前类是否真的是一个控制器或Dao,即使标记的类和注解不对应也没有语法错误。但在实际工作中,肯定要将专门的注解标记在对应的类上面。
②使用基于注解的bean的配置,需要额外导入一个jar包:spring-aop-4.0.0.RELEASE.jar
③需要设置自动扫描的包
< context:component-scan base-package ="com.neuedu.ioc.bean"/>
④使用注解后,默认按照类名首字母小写作为id的值,也可以使用value属性指定id,value属性名也可以省略注解
注解 id值
@Component commonComponent
public class CommonComponent {
}
@Controller(value="neueduBookAction" ) neueduBookAction
public class BookAction {
}
@Service("happyService" ) happyService
public class BookService {
}
实验31:通过注解分别创建Dao、Service、Controller★
实验32:使用context:include-filter指定扫描包时要包含的类
实验33:使用context:exclude-filter指定扫描包时不包含的类
< context:component-scan base-package ="com.neuedu.ioc.bean"/>
[1]base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包及其子包中的所有类。
[2]当需要扫描多个包时可以使用逗号分隔,
[3]如果仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类,示例:
<context:component-scan base-package="com.neuedu.component" resource-pattern="autowire/*.class"/>
[4]包含与排除
●<context:include-filter>子节点表示要包含的目标类
注意:通常需要与use-default-filters属性配合使用才能够达到“仅包含某些组件”这样的效果。
即:通过将use-default-filters属性设置为false,禁用默认过滤器,然后扫描的就只是include-filter中的规则
指定的组件了。
●<context:exclude-filter>子节点表示要排除在外的目标类
●component-scan下可以拥有若干个include-filter和exclude-filter子节
⑤使用注解进行自动装配:@Autowired注解[好处就是:连get、set方法都不用写!]
[1]首先检测标记了@Autowired注解的属性的类型
[2]根据类型进行装配
[3]如果指定类型的bean不止一个,那么根据需要被装配的属性的属性名做id的值,查找bean
[4]如果根据id值还是没有找到bean,可以使用@Qualifier注解手动指定要装配的bean的id.
实验34:使用@Autowired注解实现根据类型实现自动装配★
实验34[补充1]:如果资源类型的bean不止一个,默认根据@Autowired注解标记的成员变量名作为id查找bean,进行装配★
实验34[补充2]:如果根据成员变量名作为id还是找不到bean,可以使用@Qualifier注解明确指定目标bean的id★
实验36:Autowired注解的required属性指定某个属性允许不被设置.
实验37:在类上使用注解@Scope可以指定对象是单实例还是多实例的!
Spring && 实验IOC的更多相关文章
- Spring(一)--作用、IOC容器细节、搭配环境、Spring实验
1.Spring作用: 1.生态体系庞大,全能型选手![springmvc是其一个子模块,jdbcTemplate能直接操作数据库!] 2.将其他组件粘合在一起 比如将S ...
- spring 中IOC实验(一)
软件151 王帅 1.三个类,Human(人类)是接口,Chinese(中国人)是一个子类,American(美国人)是另外一个子类. 代码如下: package cn.com.chengang.s ...
- 挖坟之Spring.NET IOC容器初始化
因查找ht项目中一个久未解决spring内部异常,翻了一段时间源码.以此文总结springIOC,容器初始化过程. 语言背景是C#.网上有一些基于java的spring源码分析文档,大而乱,乱而不全, ...
- spring之IOC容器创建对象
1.术语了解 1.1组件/框架设计 侵入式设计 引入了框架,对现有的类的结构有影响:即需要实现或继承某些特定类. 例如: Struts框架非侵入式设计 引入了框架,对现有的类结构没有影响. 例如:Hi ...
- Spring之IOC/DI(反转控制/依赖注入)_入门Demo
在平时的java应用开发中,我们要实现某一个功能或者说是完成某个业务逻辑时至少需要两个或以上的对象来协作完成,在没有使用Spring的时候,每个对象在需要使用他的合作对象时,自己均要使用像new ob ...
- Spring的IOC和AOP之深剖
今天,既然讲到了Spring 的IOC和AOP,我们就必须要知道 Spring主要是两件事: 1.开发Bean:2.配置Bean.对于Spring框架来说,它要做的,就是根据配置文件来创建bean实例 ...
- Spring框架IOC容器和AOP解析
主要分析点: 一.Spring开源框架的简介 二.Spring下IOC容器和DI(依赖注入Dependency injection) 三.Spring下面向切面编程(AOP)和事务管理配置 一.S ...
- Spring总结—— IOC 和 Bean 的总结
一.Spring 官方文档中给出的 Spring 的整体结构. 二.我自己所理解的 Spring 整体结构图. 三.本次总结 Spring 核心部分 1.从上面图中可以看出,Beans 和 Conte ...
- spring的IOC和AOP
spring的IOC和AOP 1.解释spring的ioc? 几种注入依赖的方式?spring的优点? IOC你就认为他是一个生产和管理bean的容器就行了,原来需要在调用类中new的东西,现在都是 ...
随机推荐
- Spring中注解
@Autowired :spring注解 @Resource :J2EE注解 @Transactional(rollbackFor=Exception.class):指定回滚 @RequestMapp ...
- cxf与struts2拦截器冲突的解决方案
最近学习接口,学习了下cxf,用tomcat部署访问的时候,发现接口不能访问:百度了很多,最终找到比较好的解决方案: sturts2配置: <!-- 设置strus拦截器 --> < ...
- Rod Johnson
Spring Framework创始人,著名作者. Rod在悉尼大学不仅获得了计算机学位,同时还获得了音乐学位.更令人吃惊的是在回到软件开发领域之前,他还获得了音乐学的博士学位. 有着相当丰富的C/C ...
- codeforces 686D D. Kay and Snowflake(dfs)
题目链接: D. Kay and Snowflake time limit per test 3 seconds memory limit per test 256 megabytes input s ...
- UICollectionView基础/UICollectionViewCell的四种创建方式
前言 UICollectionViewCell的四种创建方式:http://blog.csdn.net/ZC_Huang/article/details/52002302 这个控件,看起来与UITab ...
- 守护线程Daemon的理解
1.守护线程伴随着主线程的销毁而销毁: 2.jvm虚拟机中有很多守护线程,随着main函数的结束而结束,自动回收栈中的内容. Thread t1 = new Thread(){ @Override p ...
- JS处理Cookie
<script>function GetCookieVal(offset)//获得Cookie解码后的值{var endstr = document.cookie.indexOf (&qu ...
- Mysql数据库的触发器、存储引擎和存储过程
数据库的触发器 1.触发器 触发器是MySQL响应以下任意语句而自动执行的一条MySQL语句(或位于BEGIN和END语句之间的一组语句): DELETE,INSERT,UPDATE 我们可以监视某表 ...
- bzoj 1614: [Usaco2007 Jan]Telephone Lines架设电话线【二分+spfa】
二分答案,然后把边权大于二分值的的边赋值为1,其他边赋值为0,然后跑spfa最短路看是否满足小于等于k条边在最短路上 #include<iostream> #include<cstd ...
- bzoj 2111: [ZJOI2010]Perm 排列计数【树形dp+lucas】
是我想复杂了 首先发现大于关系构成了一棵二叉树的结构,于是树形dp 设f[i]为i点的方案数,si[i]为i点的子树大小,递推式是\( f[i]=f[i*2]*f[i*2+1]*C_{si[i]-1} ...