Spring笔记整理(一)之IOC
IOC与DI入门
介绍
-
ssh
hibernate+struts2+spring
-
ssm
mybatis+springMVC+spring
spring的3大知识点
-
IOC+DI
-
AOP
-
声明式事务
一、spring的概述
-
spring: 是java 分层的se/ee的full-stack(一站式) 开源框架
为EE的每一层都提供了解决技术:
- web: struts2 springMVC
- service: spring(IOC AOP 声明式事务)
- dao: hibernate springJDBCTemplate(dbutils类似)
-
spring的作用
-
解耦合
-
声明式事务
-
集成junit更加方便的进行分层测试
-
对优秀框架进行集成
-
AOP思想(在某些方法之前和之后进行增强)
…
-
-
spring的体系结构
二、spring的IOC快速入门
IOC: 控制反转
- 简单理解: 把创建对象的权利交给spring了
- 底层技术支持: 工厂+反射+配置文件 (spring都封装好了)
- 解决的问题: 解耦合
spring的环境搭建
-
导包
-
beans core context expression(四个核心)
-
日志包
spring在运行的过程中 会加载一个日志包 commons-logging.jar 提供了日志功能 但是企业不用它记录日志 apache--log4j.jar 企业开发用的最多的是它记录日志 log4j.properties
spring在加载的过程中会加载commons-logging.jar日志包
commons-logging.jar日志包的内部会看有没有apache–log4j.jar包
如果有 就是用commons-log4j.jar功能来记录日志
如果没有 就使用自己的
-
-
创建一个类
-
在src下面创建配置文件,建议名-applicationContext.xml
-
完整约束
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns="http://www.springframework.org/schema/beans" 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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> </beans>
-
-
测试
三、ioc的配置文件内容
标签
-
bean标签: 指定要实例化的对象
-
id属性: 唯一标识 可以为任意值 但是整个xml唯一
-
class属性: 类的全限定名 就是通过它反射该类的实例对象
-
scope属性: 范围
重点
-
singleton: 单实例 默认值
配置文件只要一加载 就会创建该实例对象 放在spring容器中 (Map<user,实例对象>)
注意:只创建一次
当每个人过来要的时候(getBean(“user”)) 从spring容器中获取的都是同一个实例对象
-
prototype: 多实例
配置文件只要一加载 不创建该实例对象
当所有人过来要的时候(getBean(“user”)) 才创建该实例对象 放在spring容器中
注意:获取一次 创建一次 放在spring容器中
了解
-
init-method属性: 指定初始化的方法
-
destory-method属性:指定销毁的方法
-
singleton:
初始化:配置文件加载的时候 创建对象并且初始化
销毁:容器销毁 对象跟着销毁 -
prototype:
初始化:当getbean()的时候 创建对象并且初始化
销毁: 长时间不用 java垃圾回收自动回收
-
-
-
import标签:导入外部的配置文件
- resource属性:外部配置文件的地址
bean的三种创建方式
-
无参构造器创建 (掌握) 99%
<bean id="user" class="cn.dmdream.demo02.CarImpl"></bean>
-
静态工厂创建 (了解)
条件:需要先有个工厂
<bean id="user" class="cn.dmdream.demo02.BeanFactory" factory-method="createCar"></bean>
-
实例工厂创建 (了解)
<bean id="factory" class="cn.dmdream.demo02.BeanFactory"></bean> <bean id="user" factory-bean="factory" factory-method="createCar2"></bean>
四、Spring的DI
DI: 属性的依赖注入
- 简单理解: spring在通过ioc创建这个对象的时候,如果这个对象还有属性,就一并给赋值进去
- DI是在IOC的基础上进行对象的属性注入的
DI的属性注入方式
1.构造器属性注入(了解)
条件:得有有参构造器
<constructor-arg name="name" value="rose"></constructor-arg>
2.名称空间属性注入(知道)
条件:需要导入p的名称空间
<!-- 顶部约束添加 -->
xmlns:p="http://www.springframework.org/schema/p"
<!-- 底层用的还是set方式 属性需要有set方法 -->
<bean p:属性名="肉丝" p:属性名-ref="car" >
3.set属性注入(掌握)
条件:类的属性需要有set方法
<property name="name" value="jack"></property>
- 基本类型和String -> value
- 对象类型 -> ref
4.复杂(map,list []…)属性注入(掌握)
条件:set方式注入赋值属性值
-
数组类型
<property name="ss"> <!-- 数组类型 --> <list> <value>aaa</value> <value>bbb</value> <value>ccc</value> </list> </property>
-
list类型
<property name="ll"> <!-- list类型 --> <list> <value>111</value> <value>222</value> <ref bean="car"/> </list> </property>
-
map类型
<property name="mm"> <!-- map --> <map> <entry key="k1" value="aaa"></entry> <entry key="k2" value="bbbb"></entry> <entry key="k3" value-ref="car"></entry> </map> </property>
-
properties类型
<property name="properties"> <!-- properties类型 --> <props> <prop key="hibernate.username">root</prop> <prop key="hibernate.password">1234</prop> </props> </property>
五、ioc的API内容
-
ApplicationContext:接口
2个常用的实现类
-
ClassPathXmlApplicationContext
从src下加载配置文件
-
FileSystemXmlApplicationContext
从磁盘路径下加载配置文件
注意: 默认情况:配置文件只要一加载 就创建对象scope:singleton(单例对象)
-
-
扩展: beanFactory接口下的实现类加载配置(过时了)
-
beanFactory加载配置文件
默认情况下 配置文件被加载不会创建对象
get的时候 才创建
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml")); User user1 =(User)factory.getBean("user");
-
六、Spring配置文件完整版
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd">
<!--
1: 基本配置
bean标签: 指定要创建的实体类
id属性: 可以为任意值 但是在整个配置文件中唯一
class属性: 要实例化类的全限定名 反射
-->
<!-- <bean id="user" class="cn.dmdream.domain.User"></bean> -->
<!--
2: scope属性: 范围
singleton: 单实例 默认值
如果是单实例,配置文件文件只要一加载 就会创建对象 放在spring容器 (map<id,对象>)
当所有人过来问spring容器要的时候(getBean),所用人用的都是同一个对象
prototype: 多实例
如果是多实例,配置文件加载,不创建对象
当每个人过来getbean的时候,getbean一次创建一次 放在容器中
<bean id="user" class="cn.dmdream.domain.User" scope="singleton" ></bean>
<bean id="user" class="cn.dmdream.domain.User" scope="prototype" ></bean>
什么时候用默认值singleton(单实例)? 什么时候用prototype(多实例)?
action: prototype
service/dao: singleton
3 了解
singleton的对象什么时候销毁? prototype创建出来的对象什么时候销毁?
singleton的对象当spring容器关闭 对象销毁
prototype的对象 长时间不用自动被垃圾回收机制给回收了
init-method:指定初始化方法
destory-method:指定销毁方法
-->
<!-- <bean id="user" class="cn.dmdream.domain.User" scope="prototype" init-method="init" destroy-method="destory"></bean> -->
<!--
3 import:导入外部的配置文件
resource:外部配置文件的地址
web: 所有在web层创建的对象 applicationContext_web.xml
service:所有在service层创建的对象 applicationContext_service.xml
dao:所有在dao层创建的对象 applicationContext_dao.xml
<import resource="applicationContext_web.xml"/>
<import resource="applicationContext_service.xml"/>
<import resource="applicationContext_dao.xml"/>
<import resource="applicationContext_user.xml"/>
-->
<!-- bean的三种创建方式
无参构造方式
静态工厂方式(了解)
实例工厂方式(了解)
-->
<!-- 无参构造方式
<bean id="user" class="cn.dmdream.domain.User"></bean>
-->
<!-- 静态工厂方式(了解)
条件:需要有一个工厂类 在这个工厂类中还需要有一个静态方法
<bean id="user" class="cn.dmdream.utils.BeanFactory" factory-method="createUser"/>
-->
<!-- 实例工厂(了解)
条件:需要有一个工厂类 在这个工厂类中还需要有一个普通方法
<bean id="beanFactory" class="cn.dmdream.utils.BeanFactory"></bean>
<bean id="user" factory-bean="beanFactory" factory-method="createUser"></bean>
-->
<!-- DI的入门:属性的依赖注入 -->
<bean id="car" class="cn.dmdream.serviceImpl.CarImpl">
<!-- property:是set属性的方式
name:要赋值的属性名
value:要赋的值
-->
<property name="name" value="兰博基尼"></property>
<property name="price" value="2000000"></property>
</bean>
<!--
DI的注入方式:
1 构造器的方式
条件:需要有参构造方法
-->
<!-- <bean id="car" class="cn.dmdream.serviceImpl.CarImpl">
构造器的方式
name:要赋值的属性名
value:要赋的值 (针对的是基本类型和String类型)
ref: 针对的是对象类型
<conostructor-arg name="name" value="BMW"></cnstructor-arg>
<constructor-arg name="price" value="1000000"></constructor-arg>
</bean> -->
<!--
DI的注入方式:
1 set属性的方式
条件:属性必须要有set方法
name:要赋值的属性名
value:要赋的值 (针对的是基本类型和String类型)
ref: 针对的是对象类型
指向的是spring中bean的id名
-->
<!-- <bean id="person" class="cn.dmdream.serviceImpl.PersonImpl">
set属性的方式
<property name="name" value="jack"></property>
<property name="car" ref="car"></property>
</bean> -->
<!--
DI的注入方式:
1 p名称空间的方式
条件: 在配置文件中有p的名称空间
底层set方式 属性还是得有set方法
语法:
<bean p:属性名="属性值" p:属性名-ref="bean的id对象值" >
-->
<!-- <bean id="person" class="cn.dmdream.serviceImpl.PersonImpl" p:name="rose" p:car-ref="car"></bean> -->
<!-- DI:复杂属性注入 -->
<bean id="collBean" class="cn.dmdream.domain.CollBean">
<property name="ss">
<!-- 数组类型 -->
<list>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>
<property name="ll">
<!-- list类型 -->
<list>
<value>111</value>
<value>222</value>
<ref bean="car"/>
</list>
</property>
<property name="mm">
<!-- map -->
<map>
<entry key="k1" value="aaa"></entry>
<entry key="k2" value="bbbb"></entry>
<entry key="k3" value-ref="car"></entry>
</map>
</property>
<property name="properties">
<!-- properties类型 -->
<props>
<prop key="hibernate.username">root</prop>
<prop key="hibernate.password">1234</prop>
</props>
</property>
</bean>
</beans>
七、Spring配置文件完整约束
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
</beans>
IOC注解开发
一、spring整合连接池(c3p0,dbcp)
1.读取外部配置文件
<!-- 让spring知道外部的数据库连接信息的配置文件 jdbc.properties -->
<!-- 让spring能够加载jdbc.properties文件 spring提供了一个标签 可以加载外部的properties文件内容 导context的名称空间和约束 才会有提示 -->
<context:property-placeholder location="classpath:db.properties"/>
2.c3p0整合
<bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.drivername}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
3.dbcp整合
<bean id="dbcp" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
4.注意
-
在db.properties文件中,key的设置的格式一定要为
jdbc.XXX
,防止主机名(username)冲突jdbc.drivername=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://cloud.dmdream.cn:3306/zjweu jdbc.username=root jdbc.password=XXXXX
二、三种开发方式
-
全xml的配置(重要)
-
半XML半注解的配置(重要)
-
自己的类全部用注解
-
别人的类全部用xml
-
-
全注解方式
- 完全用注解的方式 完全抛弃掉xml配置文件
- 自己的类和别人的类全部用注解
- 条件:需要有一个注解类,不在加载配置文件 而是加载这个注解类
- 完全用注解的方式 完全抛弃掉xml配置文件
三、spring的IOC注解(重点)
注解的开发步骤
- 导包 spring-aop.jar
- 开启注解扫描器 告诉spring应该去那个包下面解析注解
- 配置注解组件 Component
- 测试
如何使用注解
-
导包 spring-aop.jar
-
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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
-
配置注解扫描器
<!-- 开启注解扫描器 cn.dmdream:包含自己 以及自己下面的所有子包--> <context:component-scan base-package="com.zjweu"></context:component-scan>
注解扫描扩展阅读
掌握的注解
-
@Component(“bean的id值”)
定义在类上,只要定义在了类上,那么注解扫描器只要一扫描到就会创建该类的实例对象 放在spring容器中
需要注意的事项:
spring发布了公告, @Component这个注解不维护了,要维护这个注解下面衍生出的3个注解
- @Controller(“bean的id值”) 针对的就是web层
- @Service(“bean的id值”) 针对的是service层
- @Repository(“bean的id值”) 针对的是dao层
-
@Value(“属性值”)
定义在属性字段上 针对的是基本类型和String类型。
如果使用了这个注解 该属性的set方法可以省略不写
如果要设置配置文件中的属性,使用
@Value("${属性名}")
-
@Autowired
定义在属性字段上的 针对的是对象类型
如果定义在了那个对象类型的属性身上 会自动去spring容器中找该类型的实例对象给赋值
注意: @Autowired -> 自动去spring容器中找有没有该类型的实例对象 如果有直接赋值
-
@Qualifier(“userDaoxxx”)
定义在属性字段上的 指定用该类型的哪个id名称的实例对象
注意: @Qualifier要想使用 必须结合 @Autowired 一起使用
-
@Resource(name=“userDaoxxx”)
写上name是用名称指定
注意: 相当于 @Autowired+@Qualifier(“userDaoxxx”)
了解的注解
-
@Scope("singleton"或则prototype)
定义在类上的 指定当前类是单实例还是多实例
@Scope("prototype")
-
@PostConstruct
定义在方法上 配置初始化方法
-
@PreDestroy
定义在方法上 配置销毁的方法
全注解的配置(了解)
-
条件: 注解类
package cn.dmdream.springconfig; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import com.mchange.v2.c3p0.ComboPooledDataSource; @Configuration // 表示该类是一个注解类 @ComponentScan(basePackages="cn.dmdream") //<context:component-scan base-package="cn.dmdream"></context:component-scan> @PropertySource(value="classpath:jdbc.properties")//<context:property-placeholder location="classpath:jdbc.properties"/> //@Import(value = {DataSourceconfig.class}) public class SpringConfig { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; // 自己创建c3p0连接池 给spring容器 @Bean(name="c3p0") //<bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource"> public DataSource createDataSourceC3p0() throws Exception { ComboPooledDataSource ds = new ComboPooledDataSource(); ds.setDriverClass(driver); ds.setJdbcUrl(url); ds.setUser(username); ds.setPassword(password); return ds; } // 4.3以前 要给spring配置一个解析器 来解析 ${} @Bean public static PropertySourcesPlaceholderConfigurer createPropertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); } }
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/hibernate jdbc.username=root jdbc.password=1234 #jdbc.driver=com.mysql.jdbc.Driver #jdbc.url=jdbc:oracle://localhost:3306/hibernate #jdbc.username=root #jdbc.password=1234 #jdbc.driver=com.mysql.jdbc.Driver #jdbc.url=jdbc:db2://localhost:3306/hibernate #jdbc.username=root #jdbc.password=1234
-
加载不是配置文件了 而是注解类
测试类Demo代码
package cn.dmdream.test; import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import cn.dmdream.springconfig.SpringConfig; public class SpringConfigTest { @Test public void test() throws SQLException { // 加载注解类 ApplicationContext context=new AnnotationConfigApplicationContext(SpringConfig.class); /* UserService userService=(UserService)context.getBean("userService"); userService.save();*/ DataSource ds =(DataSource)context.getBean("c3p0"); Connection con = ds.getConnection(); System.out.println(con); } }
四、spring整合Junit做测试
普通测试的缺点
- 代码复用性大
- 配置文件运行一次加载一次
Spinrg整合junit开发步骤
-
导包
- spring-test.jar Spring整合的test包
- spring-aop.jar 可以写注解
- junit.jar junit包
-
要告诉spring配置文件的地址
1、在类上使用注解,告诉spring配置文件在哪个地方
@ContextConfiguration(value=“classpath:applicationContext.xml”) 或
@ContextConfiguration(locations={“classpath:applicationContext.xml”})
-
要告诉spring谁加载配置文件 (SpringJunt4ClassRunner.class)
2、告诉spring谁加载配置文件
@Runwith(value=SpringJUnit4ClassRunner.class)
-
分层测试