Spring框架--IOC技术

news2025/5/25 11:16:48

一、Spring框架的介绍

1、Spring框架的概述

    Spring 是一个开放源代码的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003年兴起的一个轻量级的Java开发框架,由 Rod Johnson 创建。简单来说,Spring是一个分层的 JavaSE/EE full-stack(一站式) 轻量级开源框架。

    Spring 是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作 Expert One-On-One J2EE Development and Design 中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。

    Spring 的核心是控制反转(IoC 控制反转)和面向切面(AOP)。简单来说,Spring 是一个分层的 JavaSE/EEfull-stack(一站式) 轻量级开源框架。

2、Spring框架的优点

  • 方便解耦,简化开发,Spring 就是一个大工厂,可以将所有对象创建和依赖关系维护,交给 Spring 管理。IOC 的作用。
  • AOP 编程的支持,Spring 提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。(可扩展性)
  • 声明式事务的支持,只需要通过配置就可以完成对事务的管理,而无需手动编程。
  • 方便程序的测试,Spring Junit4 支持,可以通过注解方便的测试 Spring 序。
  • 方便集成各种优秀框架,Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts2HibernateMyBatisQuartz 等)的直接支持。
  • 降低 JavaEE API 的使用难度,Spring JavaEE 开发中非常难用的一些 API JDBCJavaMail、远程调用等),都提供了封装,使这些 API 应用难度大大降低。

二、Spring IOC 核心技术

1、什么是 IOC

IOC -- Inverse of Control,控制反转,将对象的创建权力反转给 Spring 框架

控制反转(Inversion of Control,缩写为 IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。

解决问题:使用 IOC 可以解决的程序耦合性高的问题,Spring 的工厂读取配置文件。

2、IOC 的程序入门

创建 Java 工程,导入坐标依赖

<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>

编写接口和实现类,编写具体的实现方法

package com.qcbyjy.service;
public interface UserService {
public void hello();
}
package com.qcbyjy.service;
public class UserServiceImpl implements UserService {
@Override
public void hello() {
System.out.println("Hello IOC!!");
}
}

编写 Spring 核心的配置文件,在 src 目录下创建 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">
<!--IOC 管理 bean-->
<bean id="userService" class="com.qcbyjy.service.UserServiceImpl"
/>
</beans>

log4j.properties 的配置文件拷贝到 resources 目录下,做为 log4j 的日志配置文件。编写测试方法。

package com.qcbyjy.test;
import com.qcbyjy.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
public class Demo1 {
/**
* 入门程序
*/
@Test
public void run1(){
// 使用 Spring 的工厂
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("applicationContext.xml");
// 通过工厂获得类:
UserService userService = (UserService)
applicationContext.getBean("userService");
userService.hello();
}
}

3、IOC 技术总结

ApplicationContext 接口,工厂的接口,使用该接口可以获取到具体的 Bean 对象。该接口下有两个具体的实现类。 

ClassPathXmlApplicationContext,加载类路径下的 Spring 配置文件。

FileSystemXmlApplicationContext,加载本地磁盘下的 Spring 配置文件。

4、Spring 框架的 Bean 管理的配置文件方式

    id 属性,Bean 起个名字,在约束中采用 ID 的约束,唯一,取值要求:必须以字母开始,可以使用字母、数字、连字符、下划线、句话、冒号 id:不能出现特殊字符。

    class 属性,Bean 对象的全路径。

    scope 属性,scope 属性代表 Bean 的作用范围。singleton 单例(默认值),最常用的方式。 prototype 多例。request 应用在 Web 项目中,每次 HTTP 请求都会创建一个新的 Bean。session 应用在 Web 项目中,同一个 HTTP Session 共享一个 Bean

    Bean 对象的创建和销毁的两个属性配置

    说明:Spring 初始化 bean 或销毁 bean 时,有时需要作一些处理工作,因此 spring 可以在创建和拆卸 bean 的时候调用 bean 的两个生命周期方法:

  • init-method,当 bean 被载入到容器的时候调用 init-method 属性指定的方法
  • destroy-method,当 bean 从容器中删除的时候调用 destroy-method 属性指定的方法

5、实例化 Bean 对象的三种方式

默认是无参数的构造方法(默认方式,基本上使用)

<bean id="us" class="com.qcbyjy.service.UserServiceImpl" />

静态工厂实例化方式

package com.qcbyjy.demo1;
import com.qcbyjy.service.UserService;
import com.qcbyjy.service.UserServiceImpl;
/**
* 静态工厂方式
*/
public class StaticFactory {
// 静态工厂方式
public static UserService createUs(){
System.out.println("通过静态工厂的方式创建 UserServiceImpl 对
象...");
// 编写很多业务逻辑 权限校验
return new UserServiceImpl();
}
}
<bean id="us" class="com.qcbyjy.demo1.StaticFactory"
factory-method="createUs" />

实例工厂实例化方式

package com.qcbyjy.demo1;
import com.qcbyjy.service.UserService;
import com.qcbyjy.service.UserServiceImpl;
/**
*
* 动态工厂方式
*
*/
public class Dfactory {
public UserService createUs(){
System.out.println("实例化工厂的方式...");
return new UserServiceImpl();
}
}
<bean id="dfactory" class="com.qcbyjy.demo1.Dfactory" />
<bean id="us" factory-bean="dfactory" factory-method="createUs" />

三、DI 依赖注入

1、依赖注入的概述

IOC DI 的概念

  • IOCInverse of Control,控制反转,将对象的创建权反转给 Spring
  • DIDependency Injection,依赖注入,在 Spring 框架负责创建 Bean 对象时,动态的将依赖对象注入到 Bean 组件中!!

2、属性的 set 方法注入值

编写属性,提供该属性对应的 set 方法,编写配置文件完成属性值的注入

package com.qcbyjy.service;
import com.qcbyjy.dao.OrderDao;
public class OrderServiceImpl implements OrderService {
// 编写成员属性,一定需要提供该属性的 set 方法
private OrderDao orderDao;
// 一定需要提供该属性的 set 方法,IOC 容器底层就通过属性的 set 方法方式注
入值
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
// 消息
private String msg;
// 年龄
private int age;
public void setMsg(String msg) {
this.msg = msg;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void saveOrder() {
System.out.println("业务层:保存订单..."+msg+" - "+age);
// 调用
orderDao.saveOrder();
}
}
package com.qcbyjy.dao;
public class OrderDaoImpl implements OrderDao {
@Override
public void saveOrder() {
System.out.println("持久层:保存订单...");
}
}
<!--DI:依赖注入-->
<bean id="os" class="com.qcbyjy.service.OrderServiceImpl">
<property name="orderDao" ref="od" />
<property name="msg" value="你好" />
<property name="age" value="30" />
</bean>
<bean id="od" class="com.qcbyjy.dao.OrderDaoImpl"></bean>

3属性构造方法方式注入值

对于类成员变量,构造函数注入。

package com.qcbyjy.demo2;
public class Car {
// 名称
private String cname;
// 金额
private Double money;
public Car(String cname, Double money) {
this.cname = cname;
this.money = money;
}
@Override
public String toString() {
return "Car{" +
"cname='" + cname + '\'' +
", money=" + money +
'}';
}
}
<bean id="car" class="com.qcbyjy.demo2.Car">
<constructor-arg name="cname" value="大奔" />
<constructor-arg name="money" value="400000" />
</bean>

4、数组,集合(List,Set,Map)Properties等的注入

package com.qcbyjy.demo3;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class CollectionBean {
// 数组
private String [] strs;
public void setStrs(String[] strs) {
this.strs = strs;
}
private List<String> list;
public void setList(List<String> list) {
this.list = list;
}
private Map<String,String> map;
public void setMap(Map<String, String> map) {
this.map = map;
}
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "CollectionBean{" +
"strs=" + Arrays.toString(strs) +
", list=" + list +
", map=" + map +
", properties=" + properties +
'}';
}
}
<!--给集合属性注入值-->
<bean id="collectionBean"
class="com.qcbyjy.demo3.CollectionBean">
<property name="strs">
<array>
<value>美美</value>
<value>小凤</value>
</array>
</property>
<property name="list">
<list>
<value>熊大</value>
<value>熊二</value>
</list>
</property>
<property name="map">
<map>
<entry key="aaa" value="老王"/>
<entry key="bbb" value="小王"/>
</map>
</property>
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>

四、多配置文件方式

1、多配置文件的加载方式

src 的目录下又多创建了一个配置文件,现在是两个核心的配置文件,那么加载这两个配置文件的方式有两种

主配置文件中包含其他的配置文件:
<import resource="applicationContext2.xml"/>
工厂创建的时候直接加载多个配置文件:
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("applicationContext.xml","applicationContext2.xml");

五、Spring 框架开发程序的方式

1、Spring 框架开发方式

1. 需求:编写 service dao 的类,演示代码

2. 技术选择:持久层使用原始的 JDBC 的程序,连接池选择的是 Druid 连接池。创建 maven 工程,导入开发的 jar

<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--mysql 驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>

创建数据库,创建表结构

create database spring_db;
use spring_db;
create table account(
id int primary key auto_increment,
name varchar(40),
money double
)character set utf8 collate utf8_general_ci;
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);

编写 JavaBean 的类

package com.qcbyjy.domain;
import java.io.Serializable;
public class Account implements Serializable {
private static final long serialVersionUID = 7355810572012650248L;
private Integer id;
private String name;
private Double money;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}

编写 AccountDao 的接口和实现类

package com.qcbyjy.dao;
import com.qcbyjy.domain.Account;
import java.util.List;
public interface AccountDao {
public List<Account> findAll();
}
package com.qcbyjy.dao;
import com.qcbyjy.domain.Account;
import com.alibaba.druid.pool.DruidDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class AccountDaoImpl implements AccountDao {
// 注入连接池对象
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 查询所有的数据
* @return
*/
@Override
public List<Account> findAll() {
/*
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring_db");
dataSource.setUsername("root");
dataSource.setPassword("root");
*/
List<Account> list = new ArrayList<>();
Connection connection = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
// 获取连接
connection = dataSource.getConnection();
// 编写 sql 语句
String sql = "select * from account";
// 预编译
stmt = connection.prepareStatement(sql);
// 查询
rs = stmt.executeQuery();
// 遍历,封装数据
while (rs.next()){
Account account = new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
list.add(account);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return list;
}
}
package com.qcbyjy.service;
import com.qcbyjy.domain.Account;
import java.util.List;
public interface AccountService {
public List<Account> findAll();
}
package com.qcbyjy.service;
import com.qcbyjy.dao.AccountDao;
import com.qcbyjy.domain.Account;
import java.util.List;
public class AccountServiceImpl implements AccountService {
// 依赖注入
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
/**
* 查询所有的数据
* @return
*/
@Override
public List<Account> findAll() {
return accountDao.findAll();
}
}

编写配置文件

<?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.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"
/>
<property name="url" value="jdbc:mysql:///spring_db" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<!--管理 bean-->
<bean id="accountService"
class="com.qcbyjy.service.AccountServiceImpl">
<property name="accountDao" ref="accountDao" />
</bean>
<bean id="accountDao" class="com.qcbyjy.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>

编程测试程序

package com.qcbyjy.test;
import com.qcbyjy.domain.Account;
import com.qcbyjy.service.AccountService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class Demo1 {
@Test
public void run1(){
ApplicationContext ac = new
ClassPathXmlApplicationContext("applicationContext.xml");
AccountService accountService = (AccountService)
ac.getBean("accountService");
// 调用方法
List<Account> list = accountService.findAll();
for (Account account : list) {
System.out.println(account);
}
}
}

六、IOC 注解的方式

1、IOC注解方式的快速入门

IOC 注解的方式依赖没有变化

编写接口和实现类

package com.qcbyjy.demo2;
public interface UserService {
public void hello();
}
package com.qcbyjy.demo2;
import org.springframework.stereotype.Component;
/**
* <bean id="us" class="com.qcbyjy.demo2.UserServiceImpl" />
*/
// 组件,作用:把当前类使用 IOC 容器进行管理,如果没有指定名称,默认使用类名,
首字母是小写。userServiceImpl。或者自己指定名称
@Component(value = "us")
public class UserServiceImpl implements UserService {
@Override
public void hello() {
System.out.println("Hello IOC 注解...");
}
}

在需要管理的类上添加@Component 注解

@Component(value = "us")
public class UserServiceImpl implements UserService {
@Override
public void hello() {
System.out.println("Hello IOC 注解...");
}
}

编写配置文件,重点是开启注解扫描。

<?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">
<!--开启注解扫描
<context:component-scan base-package="com.qcbyjy.demo2" />
-->
<!--开启注解扫描 com.qcbyjy.所有的包中的所有的类 -->
<context:component-scan base-package="com.qcbyjy" />
</beans>

编写测试方法

package com.qcbyjy.test;
import com.qcbyjy.demo2.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
public class Demo2 {
/**
* IOC 注解方式的入门
*/
@Test
public void run1(){
// 工厂
ApplicationContext ac = new
ClassPathXmlApplicationContext("applicationContext_anno.xml");
// 获取对象
UserService userService = (UserService) ac.getBean("us");
userService.hello();
}
}

1.6.2 2. 常用的注解

bean 管理类常用的 4 个注解(作用相同,推荐使用在不同分层上)

  • @Component 普通的类
  • @Controller 表现层@Service 业务层
  • @Repository 持久层

依赖注入常用的注解

  • @Value 用于注入普通类型(Stringintdouble 等类型)
  • @Autowired 默认按类型进行自动装配(引用类型)
  • @Qualifier @Autowired 一起使用,强制使用名称注入
  • @Resource Java 提供的注解,也被支持。使用 name 属性,按名称注入

对象生命周期(作用范围)注解

  • @Scope 生命周期注解,取值 singleton(默认值,单实例)和 prototype(多

例)

初始化方法和销毁方法注解(了解)

  • @PostConstruct 相当于 init-method
  • @PreDestroy 相当于 destroy-method

具体的代码如下

package com.qcbyjy.demo3;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
// 默认当前类名就是 ID 名称,首字母小写
@Component(value = "c")
// @Controller
// @Service(value = "c")
// @Repository(value = "c")
// @Scope(value = "singleton") // 默认值,单例的
// @Scope(value = "prototype") // 多例的
public class Car {
// 注解注入值,属性 set 方法是可以省略不写的。
// 只有一个属性,属性的名称是 value,value 是可以省略不写的
@Value("大奔 2")
private String cname;
@Value(value = "400000")
private Double money;
// 也不用提供 set 方法
// 按类型自动装配的注解,和 id 名称没有关系
@Autowired
// 按 id 的名称注入,Qualifier 不能单独使用,需要 Autowired 一起使用。
// @Qualifier(value = "person")
// @Resource Java 提供的注解,按名称注入对象,属性名称是 name
// @Resource(name = "person")
private Person person;
/**
* Car 对象创建完成后,调用 init 方法进行初始化操作
*/
@PostConstruct
public void init(){
System.out.println("操作...");
}
/*
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
*/
@Override
public String toString() {
return "Car{" +
"cname='" + cname + '\'' +
", money=" + money +
", person=" + person +
'}';
}
}
package com.qcbyjy.demo3;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component(value = "person")
public class Person {
@Value("张三")
private String pname;
@Override
public String toString() {
return "Person{" +
"pname='" + pname + '\'' +
'}';
}
}
package com.qcbyjy.test;
import com.qcbyjy.demo2.UserService;
import com.qcbyjy.demo3.Car;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
public class Demo3 {
@Test
public void run1(){
// 工厂
ApplicationContext ac = new
ClassPathXmlApplicationContext("applicationContext_anno.xml");
// 获取对象
Car car = (Car) ac.getBean("c");
System.out.println(car);
}
}

3、IOC 纯注解的方式

纯注解的方式是微服务架构开发的主要方式,所以也是非常的重要。纯注解的目的是替换掉所有的配置文件。但是需要编写配置类。

编写实体类

package com.qcbyjy.demo4;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Order {
@Value("北京")
private String address;
@Override
public String toString() {
return "Order{" +
"address='" + address + '\'' +
'}';
}
}

编写配置类,替换掉 applicationContext.xml 配置文件

package com.qcbyjy.demo4;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* Spring 的配置类,替换掉 applicationContext.xml
*
*/
// 声明当前类是配置类
@Configuration
// 扫描指定的包结构
@ComponentScan(value = "com.qcbyjy.demo4")
public class SpringConfig {
}

测试方法的编写

package com.qcbyjy.test;
import com.qcbyjy.demo4.Order;
import com.qcbyjy.demo4.SpringConfig;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import
org.springframework.context.annotation.AnnotationConfigApplicationCo
ntext;
public class Demo4 {
/**
* 编写程序,需要加载配置类
*/
@Test
public void run1(){
// 创建工厂,加载配置类
ApplicationContext ac = new
AnnotationConfigApplicationContext(SpringConfig.class);
// 获取到对象
Order order = (Order) ac.getBean("order");
System.out.println(order);
}
}

常用的注解总结

  • @Configuration 声明是配置类
  • @ComponentScan 扫描具体包结构的
  • @Import 注解 Spring 的配置文件可以分成多个配置的,编写多个配置类。用于导入其他配置类
package com.qcbyjy.demo4;
import org.springframework.context.annotation.Configuration;
/**
* 新的配置类
*
*/
@Configuration // 声明配置类
public class SpringConfig2 {
}
// 声明当前类是配置类
@Configuration
// 扫描指定的包结构
@ComponentScan(value = "com.qcbyjy.demo4")
// @ComponentScan(value = {"com.qcbyjy.demo4","com.qcbyjy.demo3"})
// 引入新的配置类
@Import(value = {SpringConfig2.class})
public class SpringConfig {

@Bean 注解 只能写在方法上,表明使用此方法创建一个对象,对象创建完成保存到 IOC 容器中

package com.qcbyjy.demo4;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import javax.sql.DataSource;
/**
*
* Spring 的配置类,替换掉 applicationContext.xml
*
*/
// 声明当前类是配置类
@Configuration
// 扫描指定的包结构
@ComponentScan(value = "com.qcbyjy.demo4")
// @ComponentScan(value = {"com.qcbyjy.demo4","com.qcbyjy.demo3"})
// 引入新的配置类
@Import(value = {SpringConfig2.class})
public class SpringConfig {
/**
* 创建连接池对象,返回对象,把该方法创建后的对象存入到连接池中,使用
@Bean 注解解决
<!--配置连接池对象-->
<bean id="dataSource"
class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql:///spring_db" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
*
* @return
*/
@Bean(name="dataSource")
public DataSource createDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring_db");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
}

七、Spring 框架整合 JUnit 单元测

1、Spring 框架整合 JUnit 单元测试

每次进行单元测试的时候,都需要编写创建工厂,加载配置文件等代码,比较繁琐。Spring 提供了整合 Junit 单元测试的技术,可以简化测试开发。下面开始学习该技术。

必须先有 Junit 单元测试的环境,也就是说已经导入 Junit 单元测试的 jar 包。咱们已经导入过了。使用的是 4.12 版本

再导入 spring-test 的坐标依赖

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
<scope>test</scope>
</dependency>

编写类和方法,把该类交给 IOC 容器进行管理

package com.qcbyjy.demo5;
public class User {
public void sayHello(){
System.out.println("Hello....");
}
}

编写配置文件 applicationContext_test.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="user" class="com.qcbyjy.demo5.User"/>
</beans>

编写测试代码

package com.qcbyjy.test;
import com.qcbyjy.demo5.User;
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;
/**
* Spring 整合 Junit 单元测试
*
*/
@RunWith(value = SpringJUnit4ClassRunner.class) // 运行单元测试
@ContextConfiguration(value =
"classpath:applicationContext_test.xml") // 加载类路径下的配置文件
public class Demo5 {
// 测试哪一个对象,把该对象注入进来,在测试环境下,可以使用注解的方式注
入测试的对象
// 按类型自动注入
@Autowired
private User user;
@Test
public void run1(){
// 创建工厂,加载配置文件......
// 调用对象的方法
user.sayHello();
}
}

2、Spring 整合单元测试(纯注解方式)

编写类和方法

package com.qcbyjy.demo6;
import org.springframework.stereotype.Component;
@Component
public class Customer {
public void save(){
System.out.println("保存客户...");
}
}

编写配置类

package com.qcbyjy.demo6;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* Spring 整合 Junit 配置类
*/
// 声明
@Configuration
// 扫描包结构
@ComponentScan(value = "com.qcbyjy.demo6")
public class SpringConfig6 {
}

编写测试方法

package com.qcbyjy.test;
import com.qcbyjy.demo6.Customer;
import com.qcbyjy.demo6.SpringConfig6;
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;
/**
* Spring 整合 Junit 注解的方式测试
*/
@RunWith(SpringJUnit4ClassRunner.class)
// 加载配置类
@ContextConfiguration(classes = SpringConfig6.class)
public class Demo6 {
// 按类型注入
@Autowired
private Customer customer;
/**
* 测试
*/
@Test
public void run1(){
customer.save();
}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2385307.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

论文阅读笔记——Emerging Properties in Unified Multimodal Pretraining

BAGEL 论文 商业闭源系统与学术/开源模型的差距很大&#xff0c;BAGEL 旨在通过开源统一架构大规模交错数据主要解决&#xff1a; 架构割裂&#xff1a;理解/生成分属两条网络&#xff0c;信息被压缩在少量条件 token 中&#xff0c;长上下文推理受限。数据贫乏&#xff1a;主…

JAVA批量发送邮件(含excel内容)

EmailSenderHtmlV1 是读取配置文件《批量发送邮件.xlsx》&#xff0c;配置sheet获取 发件人邮箱 邮箱账号 口令&#xff0c;发送excel数据sheet获取收件人邮箱 抄送人邮箱 邮件标题 第N行开始(N>1,N0默认表头) 第M行结束(M>1,M0默认表头) 附件文件夹…

Linux(Ubuntu)新建文件权限继承问题

当你在一个工作目权限为777的文件下&#xff0c;新建一个文件的时候&#xff0c;就有可能发生&#xff0c;新建的这个文件&#xff0c;权限和其他文件&#xff0c;或者工作目录不一致的问题&#xff0c;我们不可能每次新建一个文件&#xff0c;就要 sudo chmod -R 777 /PATH 所…

Java中的String的常用方法用法总结

1.1 String &#xff08;1&#xff09;声明 &#xff08;2&#xff09;字符串常量 存储字符串数据的容器&#xff1a;private final char value[] 字符串常量都存储在字符串常量池&#xff08;StringTable&#xff09;中 字符串常量池不允许存放两个相同的字符串常量 &#xff…

QGIS如何打开 ARCGIS的mxd工程文件

“SLYR”是一款由著名开源组织“北路开源”开发的一套QGIS兼容和转换ARCGIS样式、工程、设置信息的插件&#xff01;其主要功能为&#xff1a; 最近项目需要&#xff0c;我使用了一些功能&#xff0c;发现其对中文环境及中文信息支持不太好&#xff0c;还有一些其它BUG&#xf…

基于微信小程序的智能问卷调查系统设计与实现(源码+定制+解答)基于微信生态的问卷管理与数据分析系统设计

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

React 如何封装一个可复用的 Ant Design 组件

文章目录 前言一、为什么需要封装组件&#xff1f;二、 仿antd组件的Button按钮三、封装一个可复用的表格组件 (实战)1. 明确需求2. 设计组件 API3. 实现组件代码4. 使用组件 三、封装组件的最佳实践四、进阶优化 总结 前言 作为一名前端开发工程师&#xff0c;在日常项目中&a…

Canvas SVG BpmnJS编辑器中Canvas与SVG职能详解

Canvas详解与常见API 一、Canvas基础 核心特性 • 像素级绘图&#xff1a;Canvas是基于位图的绘图技术&#xff0c;通过JavaScript操作像素实现图形渲染&#xff0c;适合动态、高性能场景&#xff08;如游戏、数据可视化&#xff09;。 • 即时模式&#xff1a;每次绘制需手动…

dify多实例部署,一台机器部署多个dify实例

dify多实例部署 目的 实现在一台机器上&#xff0c;部署多个dify的实例。比如一个部署1.2版本&#xff0c;一个部署1.3版本。废话没有&#xff0c;直接上干货。 前提 你的电脑已经部署了一个dify实例&#xff0c;并成功运行。比如已经部署成功0.15.3版本。 步骤如下&#…

ML 48.机器学习之临床生存树(rpartSurv)

简介机器学习中生存树&#xff08;Survival Tree&#xff09;的原理详解 生存树是结合决策树与生存分析的机器学习模型&#xff0c;主要用于处理带有时间-事件数据&#xff08;包含删失数据&#xff09;的预测问题。其核心目标是&#xff1a;通过树状结构对数据进行递归分割&am…

HarmonyOS 应用开发,如何引入 Golang 编译的第三方 SO 库

本指南基于笔者临时修复的 ohos_golang_go 项目fork&#xff0c;解决HO 应用导入 cgo编译产物时的 crash 问题。 1. 下载 ohos_golang_go git clone https://gitcode.com/deslord/ohos_golang_go.git&#x1f4cc; 该仓库为笔者临时修复版本&#xff0c;修复了 CGO 编译模式下…

一体化雷达波明渠流量计简介

一、技术定义与核心原理 一体化雷达波明渠流量计是基于微波技术的全自动流量监测设备&#xff0c;采用 24G K 波段平面雷达技术&#xff0c;通过非接触式测量方式实现对明渠、河道、排水管网等场景的水位、流速及流量监测。其核心原理是利用雷达发射高频电磁波&#xff0c;经水…

Pr -- 耳机没有Pr输出的声音

问题 很久没更新视频号了&#xff0c;想用pr剪辑一下&#xff0c;结果使用Pr打开后发现耳机没有Pr输出的声音 解决方法 在编辑--首选项-音频硬件中设置音频硬件的输出为当前耳机设备

白皮精读:2024年国家数据基础设施建设指引【附全文阅读】

《国家数据基础设施建设指引》提出建设覆盖数据采集至安全全链条的新型基础设施,目标到 2029 年形成横向联通、纵向贯通的格局,聚焦数据可信流通、算力协同、高速传输、安全保障四大功能,明确技术架构与重点方向,强调政府与市场协同,分阶段推进试点及规模化部署,为数字中…

穿屏技巧:Mac-Windows一套鼠标键盘控制多台设备 (sharemouse6.0-Keygen)| KM-401A

文章目录 引言I sharemouse6.0介绍功能介绍关闭自动更新安装包II 安装系统对应的sharemouse软件Windowsmac版本III 知识扩展:SCP、FTP、SSH文件传输SCP配置SSH密钥免密登录FTP(File Transfer Protocal,文件传输协议)引言 基于USB进行同步键盘和鼠标事件,更流畅。 基于局域…

【写在创作纪念日】基于SpringBoot和PostGIS的各省东西南北四至极点区县可视化

目录 前言 一、空间检索简介 1、空间表结构 2、四至空间检索 二、前后端实现 1、后端实现 2、前端集成 三、成果展示 1、东部省份 2、西部省份 3、南部省份 4、北部省份 5、中部省份 四、总结 前言 在当今数字化时代&#xff0c;地理信息数据的分析与可视化对于众…

如何制作可以本地联网搜索的MCP,并让本地Qwen3大模型调用搜索回答用户问题?

环境: SearXNG Qwen3-32B-FP8 vllm 0.8.5 问题描述: 如何制作可以本地联网搜索的MCP,并让本地Qwen3大模型调用搜索回答用户问题? 解决方案: 一、安装searxng 1.按需新建模型相关文件夹 mkdir MCP chmod 777 /mnt/program/MCP2.配置conda源 nano ~/.condarc nano…

服务器硬盘虚拟卷的处理

目前的情况是需要删除逻辑卷&#xff0c;然后再重新来弄一遍。 数据已经备份好了&#xff0c;所以不用担心数据会丢失。 查看服务器的具体情况 使用 vgdisplay 操作查看服务器的卷组情况&#xff1a; --- Volume group ---VG Name vg01System IDFormat …

一个国债交易策略思路

该国债交易策略的核心在于通过分析历史价格数据来识别市场趋势&#xff0c;并在趋势确认时进行开仓操作。策略的设计思路结合了价格波动范围的计算和市场波动性的评估&#xff0c;旨在捕捉市场的短期趋势并控制风险。 首先&#xff0c;策略通过对过去5根K线的最高价和最低价进行…

【三维重建】【3DGS系列】【深度学习】3DGS的理论基础知识之如何形成高斯椭球

【三维重建】【3DGS系列】【深度学习】3DGS的理论基础知识之如何形成高斯椭球 文章目录 【三维重建】【3DGS系列】【深度学习】3DGS的理论基础知识之如何形成高斯椭球前言高斯函数一维高斯多维高斯 椭球基本定义一般二次形式 3D高斯椭球3D高斯与椭球的关系各向同性(Isotropic)和…