Spring技术是JavaEE开发必备技能,企业开发技术选型命中率>90%
专业角度
学习Spring框架设计思想
学习基础操作,思考操作与思想间的联系
学习案例,熟练应用操作的同时,体会思想
第一部分:核心容器—核心概念(IoC/DI)—容器基本操作
第二部分:整合—整合数据层技术MyBatis
第三部分:AOP—核心概念—AOP基础操作—AOP实用开发
第四部分:事务—事务实用开发
代码书写现状——耦合度偏高
解决方案——使用对象时,在程序中不要主动使用new产生对象,转换为由外部提高对象
IoC(Inversion of Control)控制反转——对象的创建控制权由程序转移到外部,这种思想称为控制反转
Spring技术对IoC思想进行了实现——Spring提供了一个容器,称为IoC容器,用来充当IoC思想中的“外部”
IoC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为Bean
DI (Dependency Injection )依赖注入——在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入
目标:充分解耦
最终效果——使用对象时不仅可以直接从IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系
Step1:导入Spring坐标spring-context,对应的版本是5.2.9.RELEASE
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
Step2:定义Spring管理的类(接口)
public interface BookService {
public void save();
}
public class BookServiceImpl implements BookService {
private BookDao bookDao = new BookDaoImpl();
public void save(){
System.out.println("book service save ...");
bookDao.save();
}
}
Step3:创建Spring配置文件,配置对应类作为Spring管理的bean
<?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.xsd">
<bean id="bookDao" class="nuc.kang.spring_01_quickstart.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="nuc.kang.spring_01_quickstart.service.impl.BookServiceImpl"/>
</beans>
注意事项
bean标签表示配置bean
id属性标签表示给bean起名字
class属性表示给bean定义类型
bean定义时id属性在同一个上下文中不能重复
Step4:初始化IoC容器(Spring核心容器/Spring容器),通过容器获取bean
public class App2 {
public static void main(String[] args) {
//3.获取IoC容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//4.获取bean
// BookDao bookDao = (BookDao) ctx.getBean("bookDao");
// bookDao.save();
BookService bookService = (BookService) ctx.getBean("bookService");
bookService.save();
}
}
Step1:删除使用new的形式创建对象的代码
public class BookServiceImpl implements BookService {
//5.删除业务层中使用new的方式创建的对象
private BookDao bookDao; //= new BookDaoImpl();
public void save(){
System.out.println("book service save ...");
bookDao.save();
}
}
Step2:提供依赖对象的setter方法(容器执行setter方法)
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void save(){
System.out.println("book service save ...");
bookDao.save();
}
//6.提供对应set方法
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
Step3:配置service和dao之间的关系
<?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.xsd">
<bean id="bookDao" class="nuc.kang.spring_01_quickstart.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="nuc.kang.spring_01_quickstart.service.impl.BookServiceImpl">
<!-- 7.配置server与dao的关系-->
<!-- property标签表示配置当前bean的属性-->
<!-- name属性表示配置哪一个具体的属性-->
<!-- ref属性表示当前容器中参照哪一个bean-->
<property name="bookDao" ref="bookDao"/>
</bean>
</beans>
类别 | 描述 |
---|---|
名称 | scope |
类型 | 属性 |
所属 | bean标签 |
功能 | 定义bean的作用范围,可选范围如下:- singleton:单例(默认) - prototype:非单例 |
格式 | |
属性列表 | id:bean的id,使用容器可以通过id值获取对应的bean,在一个容器中id值唯一;class:bean的类型,即配置的bean的全路径类名 |
范例 |
类别 | 描述 |
---|---|
名称 | name |
类型 | 属性 |
所属 | bean标签 |
功能 | 定义bean的别名,可定义多个,使用逗号(,)分号(;)空格( )分隔 |
范例 |
类别 | 描述 |
---|---|
名称 | scope |
类型 | 属性 |
所属 | bean标签 |
功能 | 定义bean的作用范围,可选范围如下:- singleton:单例(默认) - prototype:非单例 |
范例 |
public class BookDaoImpl implements BookDao {
public BookDaoImpl() {
System.out.println("book dao constructor is running...");
}
public void save(){
System.out.println("book dao save...");
}
}
<bean id="bookDao" class="com.example.spring_03_bean_instance.dao.impl.BookDaoImpl"/>
public class OrderDaoFactory {
public static OrderDao getOrderDao(){
System.out.println("factory set up...");
return new OrderDaoImpl();
}
}
<bean id="orderDao" class="com.example.spring_03_bean_instance.factor.OrderDaoFactory" factory-method="getOrderDao"/>
public class UserDaoFactory {
public UserDao getUserDao(){
return new UserDaoImpl();
}
}
<bean id="userFactory" class="com.example.spring_03_bean_instance.factor.UserDaoFactory"/>
<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
//代替原始实例工厂创建对象的方法
//bean实例
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
//bean类型
public Class<?> getObjectType() {
return UserDao.class;
}
}
<bean id="userDao" class="com.example.spring_03_bean_instance.factor.UserDaoFactoryBean"/>
public class BookDaoImpl implements BookDao {
public void save(){
System.out.println("book dao save...");
}
//表示bean初始化对应的操作
public void init(){
System.out.println("init...");
}
//表示bean销毁前对应的操作
public void destory(){
System.out.println("destory...");
}
}
<bean id="bookDao" class="nuc.kang.spring_04_bean_lifecycle.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
public void destroy() throws Exception {
System.out.println("service destory");
}
public void afterPropertiesSet() throws Exception {
System.out.println("service init");
}
public void save(){
System.out.println("book service save...");
}
}
容器关闭前触发bean的销毁
关闭容器方式:
ConfigurableApplicationContext接口close()操作
ConfigurableApplicationContext接口RegisterShutdownHook()操作
public class AppForLifeCycle {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
//ctx.registerShutdownHook();
ctx.close();
}
}
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
<bean id="bookDao" class="nuc.edu.spring_05_di_set.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="nuc.edu.spring_05_di_set.service.impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"/>
</bean>
public class BookDaoImpl implements BookDao {
private int connectionNum;
private String databaseName;
public void setConnectionNum(int connectionNum) {
this.connectionNum = connectionNum;
}
public void setDatabaseName(String databaseName) {
this.databaseName = databaseName;
}
public void save(){
System.out.println("book dao save..."+ databaseName+","+connectionNum);
}
}
<bean id="bookDao" class="nuc.edu.spring_05_di_set.dao.impl.BookDaoImpl">
<property name="databaseName" value="KLSQL"/>
<property name="connectionNum" value="1230"/>
</bean>
public class BookServiceImpl implements BookService {
private BookDao bookDao;
private UserDao userDao;
public BookServiceImpl(BookDao bookDao, UserDao userDao) {
this.bookDao = bookDao;
this.userDao = userDao;
}
}
<bean id="bookDao" class="nuc.kang.spring_06_di_constructor.dao.impl.BookDaoImpl"/>
<bean id="userDao" class="nuc.kang.spring_06_di_constructor.dao.impl.UserDaoImpl"/>
<bean id="bookService" class="nuc.kang.spring_06_di_constructor.service.impl.BookServiceImpl">
<constructor-arg name="bookDao" ref="bookDao"/>
<constructor-arg name="userDao" ref="userDao"/>
</bean>
public class BookDaoImpl implements BookDao {
private int connectionNum;
private String databaseName;
public BookDaoImpl(int connectionNum, String databaseName) {
this.connectionNum = connectionNum;
this.databaseName = databaseName;
}
}
<bean id="bookDao" class="nuc.kang.spring_06_di_constructor.dao.impl.BookDaoImpl">
<constructor-arg name="databaseName" value="klsql"/>
<constructor-arg name="connectionNum" value="999"/>
</bean>
<bean id="bookDao" class="nuc.kang.spring_06_di_constructor.dao.impl.BookDaoImpl">
<constructor-arg type="java.lang.String" value="klsql"/>
<constructor-arg type="int" value="999"/>
</bean>
<bean id="bookDao" class="nuc.kang.spring_06_di_constructor.dao.impl.BookDaoImpl">
<constructor-arg index="1" value="klsql"/>
<constructor-arg index="0" value="999"/>
</bean>
强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
可选依赖使用setter注入进行,灵活性强
Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
自己开发的模块推荐使用setter注入
IoC根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配
自动装配方式:
配置中使用bean标签autowire属性设置自动装配的类型
<bean id="bookDao" class="nuc.kang.spring_07_di_autoware.dao.Impl.BookDaoImpl"/>
<bean id="bookService" class="nuc.kang.spring_07_di_autoware.service.Impl.BookServiceImpl" autowire="byType"/>
<property name="array">
<array>
<value>100</value>
<value>200</value>
<value>300</value>
</array>
</property>
<property name="list">
<list>
<value>kang</value>
<value>lei</value>
<value>nuc</value>
</list>
</property>
<property name="set">
<set>
<value>kang</value>
<value>lei</value>
<value>nuc</value>
<value>edu</value>
</set>
</property>
<property name="map">
<map>
<entry key="country" value="China"/>
<entry key="province" value="ShanXi"/>
<entry key="city" value="LvLiang"/>
</map>
</property>
<property name="properties">
<props>
<prop key="country">china</prop>
<prop key="province">shanxi</prop>
<prop key="city">lvliang</prop>
</props>
</property>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.16</version>
</dependency>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
<?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"
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">
</beans>
<context:property-placeholder location="jdbc.properties"/>
<bean class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/>
<context:property-placeholder location="jdbc.properties,msg.properties" />
<context:property-placeholder location="*.properties"/>
<context:property-placeholder location="classpath:*.properties"/>
<context:property-placeholder location="classpath*:*.properties"/>
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\JavaEE\\Spring_10_container\\src\\main\\resources\\applicationContext.xml");
ApplicationContext ctx = new ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml","bean2.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
BookDao bookDao = ctx.getBean("bookDao",BookDao.class);
BookDao bookDao = ctx.getBean(BookDao.class);