title: Day65-Spring入门
date: 2021-04-12 10:56:51
author: Liu_zimo
Spring
-
工程构建(IDEA)
-
创建maven工程,(Spring aop/Spring ioc)
-
设置项目结构,Project Setting中 Project 设置Java JDK版本
-
模块中选择+,选择web,选中Spring aop工程,修改文件路径
src\main\webapp
-
Spring简介
- Spring是分层的Java SE/EE应用full-stack轻量级开源框架,以loC ( Inverse OfControl:反转控制)和AOP ( Aspect Oriented Programming:面向切面编程)为内核
- 提供了展现层SpringMVC和持久层Spring JDBCTemplate以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的JavaEE 企业应用开源框架。
- 发展历史:Rod Johnson (Spring之父)
- 1997年,IBM提出了EJB的思想
- 1998年,SUN制定开发标准规范EJB1.0
- 1999年,EJB1.1发布
- 2001年,EJB2.0发布
- 2003年,EJB2.1发布
- 2006年,EJB3.0发布
Spring优势
- 方便解耦,简化开发
通过Spring提供的loC容器,可以将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的过度耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用 - AOP编程的支持
通过Spring的AOP功能,方便进行面向切面编程,许多不容易用传统OOP实现的功能可以通过AOP轻松实现 - 声明式事务的支持
可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务管理,提高开发效率和质量 - 方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情 - 方便集成各种优秀框架
Spring对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的支持 - 降低JavaEE API的使用难度
Spring对JavaEEAPI(如JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些API的使用难度大为降低 - Java源码是经典学习范例
Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。它的源代码无意是Java技术的最佳实践的范例
Spring体系结构
- Core Container:核心容器
- AOP、Aspects、lnstrumentation、Messaging
- Data Access/lntegration:JDBC、ORM、OXM、JMS、Transactions
- Web:WebSocket、Servlet、Web、Portlet
Spring入门
-
原始开发步骤:
UserDao userDao = new UserDaoImpl()
Spring开发步骤
- 导入Spring框架(jar包/坐标)
- 实现Dao接口和DaoImpl实现类
- 创建Spring核心XML配置文件
- 将DaoImpl实现类配置到XML文件中
- 通过Spring客户端.getBean(id标识)
Spring配置文件
Bean标签基本配置
用于配置对象交由Spring来创建,默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功。
- 基本属性:
- id:Bean实例在Spring容器中的唯一标识
- class:Bean的全限定名称
Bean标签范围配置
<bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl" scope="singleton/prototype"></bean>
- scope:指对象的作用范围,取值如下:
取值范围 | 说明 |
---|---|
singleton | 默认值,单例的 |
prototype | 多例的 |
request | WEB项目中,Spring创建一个Bean的对象,将对象存入到request域中 |
session | WEB项目中,Spring创建一个Bean的对象,将对象存入到session域中 |
global session | WEB项目中,应用在Portlet环境,如果没有Portlet环境那么globalSession相当于session |
- 当scope的取值为singleton时
- Bean的实例化个数:1个
- Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
- Bean的生命周期:
- 对象创建:当应用加载,创建容器时,对象就被创建了
- 对象运行:只要容器在,对象一直活着
- 对象销毁:当应用卸载,销毁容器时,对象就被销毁了
- 当scope的取值为prototype时
- Bean的实例化个数:多个
- Bean的实例化时机:当调用getBean()方法时实例化Bean
- 对象创建:当使用对象时,创建新的对象实例
- 对象运行:只要对象在使用中,就一直活着
- 对象销毁:当对象长时间不用时,被Java的垃圾回收器回收了
Bean生命周期配置
- init-method:指定类中的初始化方法名称
- destroy-method:指定类中销毁方法名称
<bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl" init-method="init" destroy-method="destory"></bean>
Bean实例化三种方式
- 无参构造方法实例化
- 工厂静态方法实例化
- 工厂实例方法实例化
package com.zimo.dao;
/**
* @author Liu_zimo
* @version v0.1 by 2021/4/12 14:21
*/
public interface UserDao {
public void save();
}
-
无参构造
<bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl" init-method="init" destroy-method="destory">
package com.zimo.dao.impl; import com.zimo.dao.UserDao; /** * @author Liu_zimo * @version v0.1 by 2021/4/12 14:22 */ public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("save..."); } public void init(){ System.out.println("init..."); } public void destory(){ System.out.println("destory..."); } }
-
工厂静态
<bean id="userDao" class="com.zimo.factory.StaticFactory" factory-method="getUserDao"></bean>
package com.zimo.factory; import com.zimo.dao.UserDao; import com.zimo.dao.impl.UserDaoImpl; /** * @author Liu_zimo * @version v0.1 by 2021/4/12 15:15 */ public class StaticFactory { public static UserDao getUserDao(){ return new UserDaoImpl(); } }
-
工厂实例
<!-- 先创建工厂实例,在通过工厂实例找到对象实例 --> <bean id="factory" class="com.zimo.factory.DynamicFactory"></bean> <bean id="userDao" factory-bean="factory" factory-method="getUserDao"></bean>
package com.zimo.factory; import com.zimo.dao.UserDao; import com.zimo.dao.impl.UserDaoImpl; /** * @author Liu_zimo * @version v0.1 by 2021/4/12 15:23 */ public class DynamicFactory { public UserDao getUserDao(){ return new UserDaoImpl(); } }
Bean的依赖注入分析
目前UserService实例和UserDao实例都存在与Spring容器中,当前的做法是在容器外部获得UserService实例和UserDao实例,然后在程序中进行结合
因为UserService和UserDao都在Spring容器中,而最终程序直接使用的是UserService,所以可以在Spring容器中,将UserDao设置到UserService内部
Bean的依赖注入
- 概念:
- 依赖注入(Dependency Injection):它是Spring框架核心IOC的具体实现
- 在编写程序时,通过控制反转,把对象的创建交给了Spring,但是代码中不可能出现没有依赖的情况。IOC解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。
- 那这种业务层和持久层的依赖关系,在使用Spring之后,就让Spring来维护了。简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。
- 方式:
怎么将UserDao怎样注入到UserService内部呢?- 构造方法
- set方法
- Set方式实现(无法自己new对象)
package com.zimo.service.Impl;
import com.zimo.dao.UserDao;
import com.zimo.service.UserService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author Liu_zimo
* @version v0.1 by 2021/4/12 15:31
*/
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void Save() {
// ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
// UserDao userDao = (UserDao) app.getBean("userDao");
// userDao.save();
this.userDao.save();
}
}
<bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.zimo.service.Impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
-
P命名空间注入本质也是set方法注入,但比起上述的set方法注入更加方便,主要体现在配置文件中,如下:
首先,需要引入P命名空间:
<?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" <!--p命名空间--> xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl"></bean> <bean id="userService" class="com.zimo.service.Impl.UserServiceImpl" p:userDao-ref="userDao" ></bean> </beans>
- 构造方式
package com.zimo.service.Impl;
import com.zimo.dao.UserDao;
import com.zimo.service.UserService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author Liu_zimo
* @version v0.1 by 2021/4/12 15:31
*/
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserServiceImpl(){}
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void Save() {
this.userDao.save();
}
}
<bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.zimo.service.Impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao"></constructor-arg> <!--构造注入-->
</bean>
Bean的依赖注入的数据类型
上面的操作,都是注入的引用Bean,处了对象的引可以注入,普通数据类型,集合等都可以在容器中进行注入
- 注入数据的三种数据类型
- 普通数据类型:value
- 引用数据类型:ref
- 集合数据类型
package com.zimo.domain;
/**
* @author Liu_zimo
* @version v0.1 by 2021/4/12 16:43
*/
public class User {
private String name;
private String addr;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getAddr() { return addr; }
public void setAddr(String addr) { this.addr = addr; }
}
-------------------------------------------------------------------
package com.zimo.dao.impl;
import com.zimo.dao.UserDao;
/**
* @author Liu_zimo
* @version v0.1 by 2021/4/12 14:22
*/
public class UserDaoImpl implements UserDao {
private String username;
private int age;
public void setUsername(String username) { this.username = username; }
public void setAge(int age) { this.age = age; }
public void setList(List<String> list) { this.list = list; }
public void setUserMap(Map<String, User> userMap) { this.userMap = userMap; }
public void setProperties(Properties properties) { this.properties = properties; }
@Override
public void save() { System.out.println("save..." + "username:" + username + ",age:" + age); }
}
- 普通方式注入
<bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl">
<property name="username" value="张三"></property>
<property name="age" value="18"></property>
</bean>
- 集合注入
<bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl">
<property name="list">
<list>
<value>aaa</value><value>bbb</value><value>ccc</value>
</list>
</property>
<property name="userMap">
<map>
<entry key="u1" value-ref="user1"></entry>
<entry key="u1" value-ref="user2"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="p1">pppp1</prop>
<prop key="p2">pppp2</prop>
<prop key="p3">pppp3</prop>
</props>
</property>
</bean>
<bean id="user1" class="com.zimo.domain.User">
<property name="name" value="tom"/>
<property name="addr" value="bj"/>
</bean>
<bean id="user2" class="com.zimo.domain.User">
<property name="name" value="jery"/>
<property name="addr" value="nj"/>
</bean>
<bean id="userService" class="com.zimo.service.Impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
引入其他配置文件(分模块开发)
实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而在Spring主配置文件通过import标签进行加载
<import resource="applicationContext-user.xml"/>
知识点整理
<bean>
标签- id属性:在容器中Bean实例的唯一标识,不允许重复
- class属性:要实例化的Bean的全限定名
- scope属性:Bean的作用范围,常用是singleton(默认)和prototype
<property>
标签:属性注入- name属性:属性名称
- value属性:注入的普通属性值
- ref属性:注入的对象引用值
<list>
标签<map>
标签<properties>
标签
<constructor-arg>
标签
<import>
标签:导入其他的spring的分文件
Spring相关API
- applicationContext:接口类型,代表应用上下文,可以通过其实例获得Spring容器中的Bean对象
ClassPathXmlApplicationContext
它是从类的根路径下加载配置文件推荐使用这种FileSystemXmlApplicationContext
它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。AnnotationConfigApplicationContext
当使用注解配置容器对象时,需要使用此类来创建spring容器。它用来读取注解。
- getBean()方法使用
UserDao userdao1 = (UserDao)app.getBean("userDao");
UserDao userdao2 = app.getBean(UserDao.class);
- 其中,当参数的数据类型是字符串时,表示根据Bean的id从容器中获得Bean实例,返回是Object,需要强转
- 当参数的数据类型是Class类型时,表示根据类型从容器中匹配Bean实例,当容器中相同类型的Bean有多个时,则此方法会报错。
Spring配置数据源
数据源(连接池)
- 数据源的作用:
- 数据源(连接池)是提高程序性能如出现的
- 事先实例化数据源,初始化部分连接资源
- 使用连接资源时从数据源中获取
- 使用完毕后将连接资源归还给数据源
- 常见的数据源(连接池):DBCP、C3PO、BoneCP、Druid等
- 数据源手动创建
@Test
// 手动创建c3p0数据源
public void test1() throws Exception {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUser("root");
dataSource.setPassword("123456");
Connection connection = dataSource.getConnection();
connection.close();
}
@Test
// 手动创建Druid数据源
public void test2() throws Exception{
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("123456");
DruidPooledConnection connection = dataSource.getConnection();
connection.close();
}
@Test
// 手动创建c3p0数据源(加载properties配置文件)
public void test3() throws Exception {
ResourceBundle rb = ResourceBundle.getBundle("jdbc"); // 读取配置文件
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(rb.getString("jdbc.driver"));
dataSource.setJdbcUrl(rb.getString("jdbc.url"));
dataSource.setUser(rb.getString("jdbc.username"));
dataSource.setPassword(rb.getString("jdbc.password"));
Connection connection = dataSource.getConnection();
connection.close();
}
--------------------------------------------------------------------
# src/main/resource/jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=123456
- Spring配置数据源
- 可以将DataSource的创建权交由Spring容器去完成
# src/main/resource/applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
</beans>
@Test
// spring容器产生数据源对象
public void test4() throws SQLException {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
DataSource dataSource = (ComboPooledDataSource) applicationContext.getBean("dataSource");
Connection connection = dataSource.getConnection();
connection.close();
}
抽取jdbc配置文件
applicationContext.xml加载jdbc.properties配置文件获得连接信息。
首先,需要引入context命名空间和约束路径:
- 命名空间:
xmIns:context="http://www.springframework.org/schema/context"
- 约束路径:
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
<?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">
<!--加载外部的properties文件-->
<context:property-placeholder location="classpath:jdbc.properties"/> <!--classpath:类加载路径-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
</beans>
Spring注解开发
Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率。
Spring原始注解
Spring原始注解主要是替代<Bean>
的配置
注解 | 说明 |
---|---|
@Component | 使用在类上用于实例化Bean |
@Controller | 使用在web层类上用于实例化Bean |
@Service | 使用在service层类上用于实例化Bean |
@Repository | 使用在dao层类上用于实例化Bean |
@Autowired | 使用在字段上用于根据类型依赖注入 |
@Qualifier | 结合@Autowired—起使用用于根据名称进行依赖注入 |
@Resource | 相当于@Autowired +@Qualifier,按照名称进行注入 |
@Value | 注入普通属性 |
@Scope | 标注Bean的作用范围 |
@PostConstruct | 使用在方法上标注该方法是Bean的初始化方法 |
@PreDestroy | 使用在方法上标注该方法是Bean的销毁方法 |
- 环境准备
package com.zimo.dao;
public interface UserDao {
public void save();
}
----------------------------------------------------------------
package com.zimo.dao.impl;
import com.zimo.dao.UserDao;
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("save....");
}
}
----------------------------------------------------------------
package com.zimo.service;
public interface UserService {
public void save();
}
----------------------------------------------------------------
package com.zimo.service.impl;
import com.zimo.dao.UserDao;
import com.zimo.service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void save() {
userDao.save();
}
}
- 传统实现方式
<?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="userDao" class="com.zimo.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.zimo.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
package com.zimo.web;
import com.zimo.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 描述
*
* @author Liu_zimo
* @version v0.1 by 2021/4/13 9:50
*/
public class UserController {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService bean = app.getBean(UserService.class);
bean.save();
}
}
- 注解方式实现
package com.zimo.service.impl;
import com.zimo.dao.UserDao;
import com.zimo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
// <bean id="userService" class="com.zimo.service.impl.UserServiceImpl"></bean>
// @Component("userService")
@Service("userService") // 功能和@Component一样,可读性强一些
@Scope("singleton") // @Scope("prototype") 单例或多例
public class UserServiceImpl implements UserService {
@Value("${jdbc.driver}") // value属性注入普通数据类型
private String driver;
// <property name="userDao" ref="userDao"></property>
@Autowired // 按照数据类型从Spring容器中进行匹配的
@Qualifier("userDao") //是按照id值从容器中进行匹配的但是主要此处@Qualifier结合@Autowired一起使用
private UserDao userDao;
@Resource(name="userDao") //@Resource相当于@Qualifier+@Autowired
private UserDao userDao1;
// 使用注解事,可省略set方法
// public void setUserDao(UserDao userDao) {
// this.userDao = userDao;
// }
public void save() {
userDao.save();
userDao1.save();
}
@PostConstruct // 构造后
public void init(){
System.out.println("init");
}
@PreDestroy // 销毁前
public void destory(){
System.out.println("destory");
}
}
--------------------------------------------------------------------
package com.zimo.dao.impl;
import com.zimo.dao.UserDao;
import org.springframework.stereotype.Component;
// <bean id="userDao" class="com.zimo.dao.impl.UserDaoImpl"></bean>
// @Component("userDao")
@Repository("userDao") // 功能一样,可读性强一些
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("save....");
}
}
<?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">
<!--加载外部的properties文件-->
<context:property-placeholder location="classpath:jdbc.properties"/> <!--classpath:类加载路径-->
<!-- 配置组件扫描 -->
<context:component-scan base-package="com.zimo"/>
</beans>
- 测试代码
package com.zimo.web;
import com.zimo.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserController {
public static void main(String[] args) {
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService bean = app.getBean(UserService.class);
bean.save();
app.close();
}
}
Spring新注解
- 使用上面的注解还不能全部替代xml配置文件,还需要使用注解替代的配置如下:
- 非自定义的Bean的配置:
<bean>
- 加载properties文件的配置:
<context:property-placeholder>
- 组件扫描的配置:
<context:component-scan>
- 引入其他文件:
<import>
- 非自定义的Bean的配置:
注解 | 说明 |
---|---|
@Configuration | 用于指定当前类是一个Spring配置类,当创建容器时会从该类上加载注解 |
@ComponentScan | 用于指定Spring在初始化容器时要扫描的包。 作用和在Spring的xml配置文件中的 <context:component-scan base-package="com.itheima"/> 一样 |
@Bean | 使用在方法上,标注将该方法的返回值存储到Spring容器中 |
@PropertySource | 用于加载.properties文件中的配置 |
@Import | 用于导入其他配置类 |
package com.zimo.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Spring核心配置文件
*
* @author Liu_zimo
* @version v0.1 by 2021/4/13 14:18
*/
// 标志该类是Spring的核心配置类
@Configuration
// <context:component-scan base-package="com.zimo"/> 组件扫描配置
@ComponentScan("com.zimo")
// <import resource="" /> 引入数据源配置文件
@Import({DataSourceConfiguration.class})
public class SpringConfiguration {
}
package com.zimo.config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/**
* 数据源配置
*
* @author Liu_zimo
* @version v0.1 by 2021/4/13 14:31
*/
// <context:property-placeholder location="classpath:jdbc.properties"/> 加载外部的properties文件
@PropertySource("classpath:jdbc.properties")
public class DataSourceConfiguration {
@Value("${jdbc.Driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean("dataSource") // Spring会将当前方法的返回值以指定名称存储到Spring容器中
public DataSource getDataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(this.driver); // 这边无法直接使用EL表达式注入
dataSource.setJdbcUrl(this.url);
dataSource.setUser(this.username);
dataSource.setPassword(this.password);
return dataSource;
}
}
public static void main(String[] args) {
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class);
UserService bean = app.getBean(UserService.class);
bean.save();
}
Spring整合Junit
- 原始Junit测试Spring的问题
- 在测试类中,每个测试方法都有以下两行代码:
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class);
UserService bean = app.getBean(UserService.class);
- 这两行代码的作用是获取容器,如果不写的话,直接会提示空指针异常。所以又不能轻易删掉。
- 上述问题解决思路
- 让SpringJunit负责创建Spring容器,但是需要将配置文件的名称告诉它
- 将需要进行测试Bean直接在测试类中进行注入
Spring集成Junit步骤
- 导入spring集成Junit的坐标
- 使用@Runwith注解替换原来的运行期
- 使用@contextconfiguration指定配置文件或配置类
- 使用@Autowired注入需要测试的对象
- 创建测试方法进行测试
package com.zimo.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Spring核心配置文件
*
* @author Liu_zimo
* @version v0.1 by 2021/4/13 14:18
*/
// 标志该类是Spring的核心配置类
@Configuration
// <context:component-scan base-package="com.zimo"/> 组件扫描配置
@ComponentScan("com.zimo")
// <import resource="" /> 引入数据源配置文件
@Import({DataSourceConfiguration.class})
public class SpringConfiguration {
}
package com.zimo.config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/**
* 数据源配置
*
* @author Liu_zimo
* @version v0.1 by 2021/4/13 14:31
*/
// <context:property-placeholder location="classpath:jdbc.properties"/> 加载外部的properties文件
@PropertySource("classpath:jdbc.properties")
public class DataSourceConfiguration {
@Value("${jdbc.Driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean("dataSource") // Spring会将当前方法的返回值以指定名称存储到Spring容器中
public DataSource getDataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(this.driver);
dataSource.setJdbcUrl(this.url);
dataSource.setUser(this.username);
dataSource.setPassword(this.password);
return dataSource;
}
}
package com.zimo.test;
import com.zimo.config.SpringConfiguration;
import com.zimo.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.sql.DataSource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})
//@ContextConfiguration("classpath:applicationContext.xml")
public class SpringJunitTest {
@Autowired
private UserService userService;
@Autowired
private DataSource dataSource;
@Test
public void test1(){
userService.save();
}
}