实战项目完成代码:SpringTest——GitHub
1.简介
Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架,以 IOC(Inverse Of Control:
反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层 Spring
MVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多
著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架。
1.1 spring 的体系结构
2.IOC(Inverse Of Control:反转控制)
2.1 过去存在的问题
程序间的耦合性过高。耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性)。对象之间的耦合越高,维护成本越高。因此对象的设计应使类和构件之间的耦合最小。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个准则就是高内聚低耦合。
以前当我们需要一个对象的时候,我们需要使用new关键字来创建对象
Student student = new Student();
但是当我们没有Student这个类时,在编译阶段就会进行报错。这种编译期依赖关系,应该在我们开发中杜绝。我们需要优化代码解决。
不知道你有没有想到什么方法?我们以前肯定在哪里解决过这种问题。
在使用JDBC操作,注册驱动时
Class.forName("com.mysql.jdbc.Driver");
Class.forName 使用了反射的机制
2.2 Spring的解决方案
工厂模式解耦
当启动服务器应用加载的时候,让一个类中的
方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。
什么是容器?什么的工厂?
容器就是用于存放创建出来的对象Map。
工厂就是负责给我们从容器中获取指定对象的类。
以前我们获取对象是自己主动的new一个对象
现在我们使用Spring后,我们获取对象时,同时跟工厂要,有工厂为我们查找或者创建对象。是被动的。
我们将我们的控制权力交给工厂来控制,这种被动接收的方式获取对象的思想就是控制反转,它是 spring 框架的核心之一。
3.IOC 快速入门
3.1 准备工作
- 创建父工程springtest,并导入坐标,删除src文件夹
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
</dependencies>
-
创建子工程day1_ioc
-
创建com.lois.dao.UserDao接口类和com.lois.dao.impl.UserDaoImpl实现类
public interface UserDao {
String findAll();
}
public class UserDaoImpl implements UserDao {
//仅是模拟dao
public String findAll() {
return "查询出所有用户";
}
}
- 创建com.lois.service.UserService接口类和com.lois.service.impl.UserServiceImpl实现类
public interface UserService {
String findAll();
}
public class UserServiceImpl implements UserService {
//此处的耦合问题我们在后面解决
private UserDao userDao = new UserDaoImpl();
public String findAll() {
return userDao.findAll();
}
}
3.2 基于XML的配置
- 在resources文件夹中创建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">
</beans>
- 让Spring管理我们写的类,在配置文件中配置service和dao
<!-- bean 标签:用于配置让 spring 创建对象,并且存入 ioc 容器之中
id 属性:对象的唯一标识。
class 属性:指定要创建对象的全限定类名-->
<bean id="userDao" class="com.lois.dao.impl.UserDaoImpl" />
<bean id="userService" class="com.lois.service.impl.UserServiceImpl"/>
- 编写com.lois.client.UserClient测试类(注意!此类在main.java包中)
/**
* 测试类
*/
public class UserClient {
public static void main(String[] args) {
//根据配置文件生成Spring容器
ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
//从IOC容器中根据id获取对象
UserDao userDao = ac.getBean("userDao", UserDao.class);
System.out.println(userDao);
//注意getBean的重载
UserService userService = (UserService) ac.getBean("userService");
System.out.println(userService);
}
}
- 执行测试
com.lois.service.impl.UserServiceImpl@3ffc5af1
com.lois.dao.impl.UserDaoImpl@5e5792a0
4. 基于XML的IOC细节
4.1 BeanFactory 和 ApplicationContext 的区别
BeanFactory 才是 Spring 容器中的顶层接口。
ApplicationContext 是它的子接口。
BeanFactory 和 ApplicationContext 的区别:
- 创建对象的时间点不一样。
- ApplicationContext:只要一读取配置文件,默认情况下就会创建对象。
- BeanFactory:什么使用什么时候创建对象。
你可以修改com.lois.client.UserClient测试类
// ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
BeanFactory ac = new XmlBeanFactory(new ClassPathResource("ApplicationContext.xml"));
然后在service和dao类中加入默认构造函数
public UserServiceImpl(){
System.out.println("构建了UserServiceImpl");
}
public UserDaoImpl(){
System.out.println("构建了UserDaoImpl");
}
使用断点调试,观察控制台输出
4.2 ApplicationContext 接口的实现类
- ClassPathXmlApplicationContext:它是从类的根路径下加载配置文件 (推荐)
- FileSystemXmlApplicationContext:它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
- AnnotationConfigApplicationContext:当我们使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。
4.3 bean 标签和管理对象细节
4.3.1 bean标签
作用:
用于配置对象让 spring 来创建的。
默认情况下它调用的是类中的无参构造函数。如果没有无参构造函数则不能创建成功。
属性:
id:给对象在容器中提供一个唯一标识。用于获取对象。
class:指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数。
scope:指定对象的作用范围。
- singleton :默认值,单例的.
- prototype :多例的.
- request :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中.
- session :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中.
- global session :WEB 项目中,应用在 Portlet 环境.如果没有 Portlet 环境那么globalSession 相当于 session.
init-method:指定类中的初始化方法名称。
destroy-method:指定类中销毁方法名称。
4.3.2 bean 的作用范围和生命周期
单例对象:scope=“singleton”
一个应用只有一个对象的实例。它的作用范围就是整个引用。
生命周期:
- 对象出生:当应用加载,创建容器时,对象就被创建了。
- 对象活着:只要容器在,对象一直活着。
- 对象死亡:当应用卸载,销毁容器时,对象就被销毁了。
多例对象:scope=“prototype”
每次访问对象时,都会重新创建对象实例。
生命周期:
- 对象出生:当使用对象时,创建新的对象实例。
- 对象活着:只要对象在使用中,就一直活着。
- 对象死亡:当对象长时间不用时,被 java 的垃圾回收器回收了。
注意:在使用单例对象的时候,创建IOC容器时就创建了单例对象,但是多例对象时是在第一次使用对象的时候创建,有点类似Mybatis中的延迟加载。Spring真的很智能!
4.3.3 实例化 Bean 的三种方式
第一种方式:使用默认无参构造函数(我们上面已经试过了,就不多说了)
第二种方式:spring 管理静态工厂——使用静态工厂的方法创建对象
- 创建静态工厂类com.lois.factory.StaticFactory
public class StaticFactory {
public static UserDaoImpl createUserDaoImpl(){
return new UserDaoImpl();
}
}
- 修改ApplicationContext.xml配置文件
<!--<bean id="userDao" class="com.lois.dao.impl.UserDaoImpl" />-->
<!-- 此种方式是:
使用 StaticFactory 类中的静态方法 createAccountService 创建对象,并存入 spring 容器
id 属性:指定 bean 的 id,用于从容器中获取
class 属性:指定静态工厂的全限定类名
factory-method 属性:指定生产对象的静态方法-->
<bean id="userDao" class="com.lois.factory.StaticFactory" factory-method="createUserDaoImpl"/>
第三种方式:spring 管理实例工厂——使用实例工厂的方法创建对象
- 创建实例工厂类com.lois.factory.InstanceFactory
public class InstanceFactory {
public UserServiceImpl createUserServiceImpl(){
return new UserServiceImpl();
}
}
- 修改ApplicationContext.xml配置文件
<!--<bean id="userService" class="com.lois.service.impl.UserServiceImpl"/>-->
<!-- 此种方式是:
先把工厂的创建交给 spring 来管理。
然后在使用工厂的 bean 来调用里面的方法
factory-bean 属性:用于指定实例工厂 bean 的 id。
factory-method 属性:用于指定实例工厂中创建对象的方法。-->
<bean id="instanceFactory" class="com.lois.factory.InstanceFactory"/>
<bean id="userService" factory-bean="instanceFactory" factory-method="createUserServiceImpl"/>
4.4 spring 的依赖注入
4.4.1 什么的依赖注入
以前我们的程序中需要一个对象使用new来实现,但是现在我们将对象都交给了Spring管理,但是程序不可能不使用其他对象(也就是说耦合性不可能消失,只能降低)。我们使用Spring将IOC容器中的对象赋值给程序中需要用的地方,这就是依赖注入。
4.4.2 构造函数注入
优势:在获取bean对象时, 注入数据是必须的
弊端:如果有一些数据用不到,也必须提供
- 修改UserService接口类和UserServiceImpl实现类
public interface UserService {
String findAll();
void show();
}
public class UserServiceImpl implements UserService {
private UserDao userDao;
private String username;
private int age;
public UserServiceImpl(UserDao userDao,String username,int age){
this.userDao = userDao;
this.username = username;
this.age = age;
}
public UserServiceImpl(){
System.out.println("构建了UserServiceImpl");
}
public void show(){
System.out.println(username+","+age+","+userDao);
}
public String findAll() {
return userDao.findAll();
}
}
- 修改ApplicationContext.xml配置文件,将以前的userService的bean注释
<!-- 使用构造函数的方式,给 service 中的属性传值
要求:
类中需要提供一个对应参数列表的构造函数。
涉及的标签:
constructor-arg
属性:
index:指定参数在构造函数参数列表的索引位置
type:指定参数在构造函数中的数据类型
name:指定参数在构造函数中的名称 (常用)
=======上面三个都是找给谁赋值,下面两个指的是赋什么值的==============
value:它能赋的值是基本数据类型和 String 类型
ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean-->
<bean id="userService" class="com.lois.service.impl.UserServiceImpl">
<constructor-arg index="0" ref="userDao"/>
<constructor-arg type="java.lang.String" value="张三"/>
<!-- Spring会将18转换成int类型,智能!-->
<constructor-arg name="age" value="18"/>
</bean>
- 在com.lois.client.UserClient的后面添加代码,执行测试
userService.show();
张三,18,com.lois.dao.impl.UserDaoImpl@6b09bb57
4.4.3 set方法注入
优势:创建对象时没有限时,不用数据时也可以调用无参构造函数
弊端:不能确保创建的对象中数据有值
- 修改UserServiceImpl类,注释刚刚写的构造函数,生成set方法
- 修改ApplicationContext.xml配置文件,并将构造函数注入的注释
<!-- 通过配置文件给 bean 中的属性传值:使用 set 方法的方式
涉及的标签:
property
属性:
name:找的是类中 set 方法后面的部分
ref:给属性赋值是其他 bean 类型的
value:给属性赋值是基本数据类型和 string 类型的
实际开发中,此种方式用的较多。-->
<bean id="userService" class="com.lois.service.impl.UserServiceImpl">
<property name="username" value="李四"/>
<property name="age" value="18"/>
<property name="userDao" ref="userDao"/>
</bean>
- 运行测试类
李四,18,com.lois.dao.impl.UserDaoImpl@20398b7c
4.4.4 注入集合属性
当变量类型是集合时,我们该如何做?
- 修改UserDao接口类和UserDaoImpl实体类,生产set方法
public interface UserDao {
String findAll();
void show();
}
public class UserDaoImpl implements UserDao {
private String[] strs;
private List<String> list;
private Set<String> set;
private Map<String,String> map;
private Properties props;
public void show() {
System.out.println(Arrays.toString(strs));
System.out.println(list);
System.out.println(set);
System.out.println(map);
System.out.println(props);
}
- 修改ApplicationContext.xml配置文件,将上次的userDao的bean标签注释起来
<!-- 注入集合数据(只要结构相同,标签可以互换)
List 结构的:
array,list,set
Map 结构的
map,entry,props,prop -->
<bean id="userDao" class="com.lois.factory.StaticFactory" factory-method="createUserDaoImpl">
<property name="strs">
<array>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</array>
</property>
<property name="list">
<set>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</set>
</property>
<property name="set">
<list>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>
<property name="map">
<map>
<entry key="username" value="aaa"/>
<entry key="password" value="123"/>
</map>
</property>
<property name="props">
<props>
<prop key="username">aaa</prop>
<prop key="password">123</prop>
</props>
</property>
</bean>
- 修改测试类,执行测试
userDao.show();
控制台输出
[aaa, bbb, ccc]
[aaa, bbb, ccc]
[aaa, bbb, ccc]
{username=aaa, password=123}
{password=123, username=aaa}
5.基于注解的 IOC 配置
5.1 环境搭建
- 创建子模块day1_annotation_ioc,将day1_ioc工程下的main文件夹复制过来(不要在idea中进行)
- 修改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"
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>
5.2 常用注解
5.2.1 用于创建对象
使用xml的时候我们用的是<bean id="" class="">
注解中使用:
@Component(一般不属于下面三个领域时使用)
衍生出来三个注解,作用及属性都是一模一样的,只不过是提供了更加明确的语义化
@Controller:一般用于表现层的注解。
@Service:一般用于业务层的注解。
@Repository:一般用于持久层的注解。
作用:
把资源让 spring 来管理。相当于在 xml 中配置一个 bean。
属性:
value:指定 bean 的 id。如果不指定 value 属性,默认 bean 的 id 是当前类的类名。首字母小写。
5.2.2 数据注入
相当于:<property name="" ref="">
<property name="" value="">
注解中使用:
@Autowired
作用:
自动按照类型注入。当使用注解注入属性时,set 方法可以省略。它只能注入其他 bean 类型。
当有多个类型匹配时,使用要注入的对象变量名称作为 bean 的 id,在 spring 容器查找,找到了也可以注入成功。找不到就报错。
@Qualifier
作用:
在自动按照类型注入的基础之上,再按照 Bean 的 id 注入。它在给字段注入时不能独立使用,必须和
@Autowire 一起使用;但是给方法参数注入时,可以独立使用。
属性:
value:指定 bean 的 id。
@Resource
作用:
直接按照 Bean 的 id 注入。它也只能注入其他 bean 类型。
属性:
name:指定 bean 的 id。
@Value
作用:
注入基本数据类型和 String 类型数据的
属性:
value:用于指定值
集合类型的注入只能通过xml来实现
5.2.2 用于改变作用范围的
相当于:<bean id="" class="" scope="">
注解中使用:
@Scope
作用:
指定 bean 的作用范围。
属性:
value:指定范围的值。
取值:singleton(默认,单例,常用) prototype(多例,常用) request session globalsession
5.2.3 生命周期(了解)
相当于:<bean id="" class="" init-method="" destroy-method="" />
注解中使用
@PostConstruct
作用:
用于指定初始化方法。
@PreDestroy
作用:
用于指定销毁方法。
5.2.4 纯注解开发
如果我们不想使用xml配置文件怎么办,Spring给我们提供了几个新注解
@Configuration
作用:
用于指定当前类是一个 spring 配置类(用于替换ApplicationContext.xml),当创建容器时会从该类上加载注解。
获取容器时需要使用AnnotationApplicationContext(有@Configuration 注解的类.class)。
属性:
value:用于指定配置类的字节码
示例:
@Configuration
public class SpringConfiguration {
}
@ComponentScan
作用:
用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的:<context:component-scan base-package="com.itheima"/>是一样的。
属性:
basePackages:用于指定要扫描的包。和该注解中的 value 属性作用一样。
示例
@Configuration
@ComponentScan("com.lois")
public class SpringConfiguration {
}
@Bean
作用:
该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。
属性:
name:给当前@Bean 注解方法创建的对象指定一个名称(即 bean 的 id)。
细节:
当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。查找的方式和Autowired注解的作用是一样的
示例
public class JdbcConfig {
@Bean(name="dataSource")
public DataSource createDataSource() {
}
@PropertySource
作用:
用于加载.properties 文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。
属性:
value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath:
@Import
作用:
用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解。当然,写上也没问题。
属性:
value[]:用于指定其他配置类的字节码。
5.3 快速入门
- Spring如何知道我们使用的是注解还是xml配置呢?使用context:component-scan标签,添加扫描的包,修改ApplicationContext.xml配置文件
<context:component-scan base-package="com.lois"/>
- 修改UserDaoImpl类
@Repository
public class UserDaoImpl implements UserDao {
public void show() {
}
public UserDaoImpl(){
System.out.println("构建了UserDaoImpl");
}
//仅是模拟dao
public String findAll() {
return "查询出所有用户";
}
}
- 修改UserServiceImpl类
@Service
@Scope("singleton")//单例
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDaoImpl;
@Value("小章")
private String username;
@Value("18")
private int age;
@PostConstruct
public void init(){
System.out.println("UserServiceImpl初始化");
}
@PreDestroy
public void destroy(){
System.out.println("UserServiceImpl销毁了");
}
public UserServiceImpl(){
System.out.println("构建了UserServiceImpl");
}
public void show(){
System.out.println(username+","+age+","+userDaoImpl);
}
public String findAll() {
return userDaoImpl.findAll();
}
}
- 修改测试类UserClient
public class UserClient {
public static void main(String[] args) {
//根据配置文件生成Spring容器
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
// BeanFactory ac = new XmlBeanFactory(new ClassPathResource("ApplicationContext.xml"));
//从IOC容器中根据id获取对象
UserDao userDao = ac.getBean("userDaoImpl", UserDao.class);
System.out.println(userDao);
//注意getBean的重载
UserService userService = (UserService) ac.getBean("userServiceImpl");
System.out.println(userService);
userService.show();
userDao.show();
ac.close();
}
}
- 执行测试
构建了UserDaoImpl
构建了UserServiceImpl
UserServiceImpl初始化
八月 16, 2019 5:00:25 下午 org.springframework.context.support.AbstractApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@4ccabbaa: startup date [Fri Aug 16 17:00:24 CST 2019]; root of context hierarchy
com.lois.dao.impl.UserDaoImpl@1dd02175
com.lois.service.impl.UserServiceImpl@31206beb
小章,18,com.lois.dao.impl.UserDaoImpl@1dd02175
UserServiceImpl销毁了
6. 小实战
学习了上面的内容,我们来写一个小实战练习一下,真正的从数据库中查一些数据。
6.1 注解+xml混用方式
- 使用sql脚本创建我们需要的数据(我们使用我写的Mybatis博客中的数据,如果你学过,可以跳过)
create database mybatistest;
use mybatistest;
drop table if exists `user`;
create table `user`(
`id` int(10) primary key auto_increment,
`name` varchar(20),
`age` int(3)
);
insert into `user`(`name`,`age`) values('小明',22);
insert into `user`(`name`,`age`) values('小红',25);
- 创建子工程day1_ioc_example,在子包中导入坐标
<dependencies>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
- 编写com.lois.dao.UserDao接口类和com.lois.dao.impl.UserDaoImpl实现类
public interface UserDao {
public List<User> findAll();
}
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Autowired
private QueryRunner runner;
public List<User> findAll() {
try{
return runner.query("select * from user",new BeanListHandler<User>(User.class));
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
- 编写com.lois.service.UserService接口类和com.lois.service.impl.UserServiceImpl实现类
public interface UserService {
public List<User> findAll();
}
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
public List<User> findAll() {
return userDao.findAll();
}
}
- 编写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"
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">
<!-- 告知spring在创建容器时要扫描的包 -->
<context:component-scan base-package="com.lois"></context:component-scan>
<!--配置QueryRunner-->
<bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
<!--注入数据源-->
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--连接数据库的必备信息-->
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/mybatistest?serverTimezone=UTC&characterEncoding=utf-8&useSSL=false"></property>
<property name="user" value="root"></property>
<property name="password" value="123123123"></property>
</bean>
</beans>
- 编写测试类com.lois.test.UserTest
public class UserTest {
@Test
public void findAllUser(){
ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
UserService userService = ac.getBean("userService", UserService.class);
System.out.println(userService.findAll());
}
}
- 执行测试方法
[User{id=1, name='小明', age=22}, User{id=2, name='小红', age=25}]
6.2 纯注解方式
- 创建子工程day1_ioc_example_withoutxml,在子包中导入坐标跟day1_ioc_example一样
- 将day1_ioc_example包中的main和test文件夹拷贝过来(不要在idea中拷贝)
- 创建配置类com.lois.config.SpringConfiguration
@Configuration
@ComponentScan("com.lois")
@PropertySource("classpath:druid.properties")
public class SpringConfiguration {
//从properties中获取信息
@Value("${driver}")
private String driver;
@Value("${url}")
private String url;
@Value("${username}")
private String username;
@Value("${password}")
private String password;
@Bean(name="runner")
public QueryRunner createQueryRunner(DataSource dataSource){
return new QueryRunner(dataSource);
}
@Bean(name="dataSource")
public DataSource createDataSource(){
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass(driver);
ds.setJdbcUrl(url);
ds.setUser(username);
ds.setPassword(password);
return ds;
}catch (Exception e){
throw new RuntimeException(e);
}
}
}
- 创建数据库信息文件druid.properties(在resources文件夹中)
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mybatistest?serverTimezone=UTC&characterEncoding=utf-8&useSSL=false
username=root
password=123123123
- 修改测试类
@Test
public void findAllUser(){
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
UserService userService = ac.getBean("userService", UserService.class);
System.out.println(userService.findAll());
}
此时我们不想在测试类使用AnnotationConfigApplicationContext,我们想使用Ioc注入的方式获取到UserService,我们该怎么办?
- 在子包中要添加坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
- 修改测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class UserTest {
@Autowired
private UserService userService;
@Test
public void findAllUser(){
System.out.println(userService.findAll());
}
}
7.作业
上面的实战我们用的是注解开发,你能使用xml开发吗?
下一章:Spring AOP简介xml注解配置、JdbcTemplate、Spring事务控制
相关内容:
初见Spring、IOC控制反转介绍及xml配置注解配置、小实战
Spring AOP简介xml注解配置、JdbcTemplate、Spring事务控制
作者编写不易,转载请注明我的博客,如果觉得写的不错的话,请随手点个赞,谢谢!!!
作者编写不易,转载请注明我的博客,如果觉得写的不错的话,请随手点个赞,谢谢!!!
作者编写不易,转载请注明我的博客,如果觉得写的不错的话,请随手点个赞,谢谢!!!