spring框架(一)

1、Spring框架:IoC和AOP

服务端三层开发:表现层、业务层、持久层 ssm, springboot, springcloud(微服务,治理组件)

Spring框架是一个流行的Java应用程序框架,它提供了许多功能来简化企业级应用程序的开发。其中,控制反转(Inversion of Control,IoC)和面向切面编程(Aspect-Oriented Programming,AOP)是Spring框架的两个重要概念。

1.控制反转(IoC):将对象的创建权力反转给Spring框架

控制反转是一种设计原则,旨在将控制权从代码中提取出来,并交由外部容器或框架来管理。在传统的程序设计中,对象之间的依赖关系通常是在代码中硬编码的,这会导致代码之间的耦合度较高,不利于维护和扩展。通过控制反转,依赖关系的管理被抽象到一个外部容器或框架中,从而降低了代码之间的耦合度。

在Spring框架中,IoC通过依赖注入(Dependency Injection,DI)的方式来实现。DI是一种将一个对象的依赖关系注入到该对象中的技术。通过使用IoC容器,开发者可以声明对象的依赖关系,而IoC容器会在运行时自动将这些依赖关系注入到对象中。这种方式使得对象的创建和依赖关系的配置更加灵活和可维护。

2. 面向切面编程(AOP):

面向切面编程是一种编程范式,旨在将应用程序中的横切关注点(cross-cutting concerns)从业务逻辑中分离出来。横切关注点是指跨多个模块或组件的通用功能,例如日志记录、事务管理、安全等。在传统的程序设计中,这些横切关注点通常会与业务逻辑混杂在一起,导致代码难以维护和扩展。

AOP通过定义“切面”来将横切关注点从业务逻辑中分离出来。一个切面可以定义为一个跨越多个模块或组件的横切关注点的集合。通过使用AOP,开发者可以将通用功能封装在独立的模块或组件中,并在需要时将其应用于业务逻辑。这种方式可以提高代码的可维护性和可重用性,并减少代码的冗余。

在Spring框架中,AOP通过代理模式来实现。代理模式是一种设计模式,其中客户端通过代理对象来访问目标对象。通过使用代理模式,Spring框架可以在运行时动态地将横切关注点应用到业务逻辑中。

2、Spring框架的优点

1.方便解耦,简化开发,Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理。IOC的作用。

2.AOP编程的支持,Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。(可扩展性)

3.声明式事务的支持,只需要通过配置就可以完成对事务的管理,而无需手动编程。

4.方便程序的测试,Spring对Junit4支持,可以通过注解方便的测试Spring程序。

5.方便集成各种优秀框架,Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts2、Hibernate、MyBatis、Quartz等)的直接支持。

6.降低JavaEE API的使用难度,Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。

3、IOC程序简单示例

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

    <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.qcby.service;
public interface UserService {public void hello();
}​package com.qcby.service;
public class UserServiceImpl implements UserService {@Overridepublic 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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">​
<!--IOC管理bean--><bean id="userService" class="com.qcby.service.UserServiceImpl" />
</beans>

编写测试方法

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

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属性指定的方法

单例的对象销毁:跟着容器工厂关闭才销毁

多例的对象销毁:垃圾回收机制进行回收的

实例化Bean对象的三种方式

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

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

②静态工厂实例化方式

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

③动态工厂实例化方式

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

4、DI依赖注入

IOC和DI的概念

​ IOC:Inverse of Control,控制反转,将对象的创建权反转给Spring

​ DI:Dependency Injection,依赖注入,在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件中

①属性的set方法注入值

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

package com.qcby.service;public class Person {// 编写成员属性,一定需要提供该属性的set方法private String name;private Integer age;private Car car;// 一定需要提供该属性的set方法,IOC容器底层就通过属性的set方法方式注入值public void setName(String name) {this.name = name;}public void setAge(Integer age) {this.age = age;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", car=" + car +'}';}
}​
package com.qcby.service;
public class Car {// 名称private String cname;// 金额private Double money;public void setCname(String cname) {this.cname = cname;}public void setMoney(Double money) {this.money = money;}@Overridepublic String toString() {return "Car{" +"cname='" + cname + '\'' +", money=" + money +'}';}
}<!--DI:依赖注入-->
<bean id="person" class="com.qcby.service.Person"><property name="car" ref="car" /><property name="name" value="张三" /><property name="age" value="30" />
</bean><bean id="car" class="com.qcby.service.Car"><property name="cname" value="奥迪" /><property name="money" value="300000.00" />
</bean>

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

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

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

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

package com.qcby.domain;
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;}@Overridepublic String toString() {return "CollectionBean{" +"strs=" + Arrays.toString(strs) +", list=" + list +", map=" + map +", properties=" + properties +'}';}
}<!--给集合属性注入值--><bean id="collectionBean" class="com.qcby.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>

5、多配置文件方式

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

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

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

① 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>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.qcby.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;}​@Overridepublic String toString() {return "Account{" +"id=" + id +", name='" + name + '\'' +", money=" + money +'}';}
}

编写AccountDao的接口和实现类

package com.qcby.dao;
import com.qcby.domain.Account;
import java.util.List;
public interface AccountDao {public List<Account> findAll();
}package com.qcby.dao;
import com.qcby.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 {  
//不使用连接池
//1、加载驱动
//2、获取连接
//3、编写sql
//4、预编译sql
//5、设置值
//6、执行sql 拿到结果集
//7、遍历结果集关闭资源
//        String driver = "com.mysql.jdbc.Driver";
//        String url="jdbc:mysql://localhost:3306/spring_db?useUnicode=true&characterEncoding=UTF-8";
//        String user = "root";
//        String password = "123456";
//        String sql = "select * from account";
//        List<Account> res = new ArrayList<Account>();
//        Class.forName(driver);
//        Connection conn = (Connection) DriverManager.getConnection(url, user, password);
//        Statement stmt = (Statement) conn.createStatement();
//        ResultSet rs = (ResultSet) stmt.executeQuery(sql);
//        while(rs.next()){
//            Account acc = new Account();
//            acc.setId(rs.getInt("id")); //获取id字段的值并设置到Account对象中
//            acc.setName(rs.getString("name")); //获取name字段的值并设置到Account对象中
//            acc.setMoney(rs.getDouble("money")); //获取money字段的值并设置到Account对象中
//            res.add(acc);
//        }
//        conn.close();
//        stmt.close();
//        rs.close();
//        return res;// 注入连接池对象private DataSource dataSource;public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;}​/*** 查询所有的数据* @return*/@Overridepublic List<Account> findAll() {/*DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql:///spring_db");dataSource.setUsername("root");dataSource.setPassword("123456");*/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.qcby.service;
import com.qcby.domain.Account;
import java.util.List;
public interface AccountService {public List<Account> findAll();
}​package com.qcby.service;
import com.qcby.dao.AccountDao;
import com.qcby.domain.Account;
import java.util.List;public class AccountServiceImpl implements AccountService {// 依赖注入private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}/*** 查询所有的数据* @return*/@Overridepublic 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/beanshttp://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="123456" /></bean><!--管理bean--><bean id="accountService" class="com.qcby.service.AccountServiceImpl"><property name="accountDao" ref="accountDao" /></bean><bean id="accountDao" class="com.qcby.dao.AccountDaoImpl"><property name="dataSource" ref="dataSource" /></bean>
</beans>

编程测试程序

package com.qcby.test;​
import com.qcby.domain.Account;
import com.qcby.service.AccountService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;public class Demo1 {@Testpublic 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);}}
}

7、IOC注解的方式

① IOC注解方式的简单示例

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

编写接口和实现类

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

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

@Component(value = "us")
public class UserServiceImpl implements UserService {@Overridepublic 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"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!--开启注解扫描<context:component-scan base-package="com.qcby.demo2" />--><!--开启注解扫描 com.qcby.所有的包中的所有的类 --><context:component-scan base-package="com.qcby" />
</beans>

编写测试方法

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

② 常用的注解

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

​ @Component 普通的类,任何地方

​ @Controller 表现层

​ @Service 业务层

​ @Repository 持久层

依赖注入常用的注解

​ @Value 用于注入普通类型(String,int,double等类型),可以省略

​ @Autowired 默认按类型进行自动装配(引用类型)

​ @Qualifier 和@Autowired一起使用,强制使用名称注入

​ @Resource Java提供的注解,也被支持。使用name属性,按名称注入对象生命周期(作用范围)注解

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

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

​ @PostConstruct 相当于init-method

​ @PreDestroy 相当于destroy-method

单例的销毁时机是跟随容器的 容器销毁对象销毁

多例的销毁时机是java的垃圾回收机制控制的

具体的代码如下

package com.qcby.domain;​
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方法进行初始化操作*/@PostConstructpublic 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;}*/@Overridepublic String toString() {return "Car{" +"cname='" + cname + '\'' +", money=" + money +", person=" + person +'}';}
}​package com.qcby.domain;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
​
@Component(value = "person")
public class Person {
​    @Value("张三")private String pname;@Overridepublic String toString() {return "Person{" +"pname='" + pname + '\'' +'}';}
}package com.qcby.test;
import com.qcby.service.UserService;
import com.qcby.domain.Car;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Demo3 {@Testpublic void run1(){// 工厂ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_anno.xml");// 获取对象Car car = (Car) ac.getBean("c");System.out.println(car);}
}

③ IOC纯注解的方式

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

编写实体类

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

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

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

测试方法的编写

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

常用的注解总结

@Configuration 声明是配置类

@ComponentScan 扫描具体包结构的

@Import注解 Spring的配置文件可以分成多个配置的,编写多个配置类。用于导入其他配置类

package com.qcby.demo4;
import org.springframework.context.annotation.Configuration;/*** 新的配置类**/
@Configuration      // 声明配置类
public class SpringConfig2 {
}// 声明当前类是配置类
@Configuration
// 扫描指定的包结构
@ComponentScan(value = "com.qcby.demo4")
// @ComponentScan(value = {"com.qcby.demo4","com.qcby.demo3"})
// 引入新的配置类
@Import(value = {SpringConfig2.class})
public class SpringConfig {
}

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

package com.qcby.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.qcby.demo4")
// @ComponentScan(value = {"com.qcby.demo4","com.qcby.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="123456" /></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("123456");return dataSource;}
}​

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

① 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.qcby.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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">​<!--整合单元测试-->
<bean id="user" class="com.qcby.demo5.User"/>​</beans>

编写测试代码

package com.qcby.test;
import com.qcby.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 {// 测试哪一个对象,把该对象注入进来,在测试环境下,可以使用注解的方式注入测试的对象// 按类型自动注入@Autowiredprivate User user;@Testpublic void run1(){// 创建工厂,加载配置文件......// 调用对象的方法user.sayHello();}
}

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

编写类和方法

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

编写配置类

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

编写测试方法

package com.qcby.test;
import com.qcby.demo6.Customer;
import com.qcby.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 {
​    // 按类型注入@Autowiredprivate Customer customer;/*** 测试*/@Testpublic void run(){customer.save();}
}

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

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

相关文章

云服务之PaaS:它有几种类型,有什么区别?

PaaS种类繁多&#xff0c;包括公共PaaS、私有PaaS和混合PaaS&#xff0c;可以根据IT人员要求的方式提供所需工具&#xff0c;以实现更快地应用交付。 新兴科技的发展、移动端的深入应用&#xff0c;让人们对应用设备的需求不断增长&#xff0c;但在需求增长的同时&#xff0c;…

大数据-Spark-关于Json数据格式的数据的处理与练习

上一篇&#xff1a; 大数据-MapReduce-关于Json数据格式的数据的处理与练习-CSDN博客 16.7 Json在Spark中的引用 依旧利用上篇的数据去获取每部电影的平均分 {"mid":1,"rate":6,"uid":"u001","ts":15632433243} {"m…

【DC-DC】AP5165B 高端电流采样 36V/1A 高调光比LED恒流驱动IC SOT89-5

产品应用原理图 5-36V耐压 3W射灯应用线路图 产品描述 AP5165B 是一款外围电路简单的连续电流模式的降压型 LED 恒流驱动芯片。在输入电压高于LED 电压时&#xff0c;可以有效地用于驱动一颗或者多颗串联 LED。输出电流可调&#xff0c;可达 1A。适用于3-36V 电压范围的非隔离…

初始化爱情的构造之旅

初始化爱情的构造之旅 The Constructive Journey of Initializing Love 在一个名为“编程之城”的奇幻世界里&#xff0c;住着两位年轻的程序员——林浩然和杨凌芸。林浩然是Java王国中的首席对象设计师&#xff0c;擅长用代码构建复杂而精巧的对象&#xff1b;而杨凌芸则是数据…

探索云性能测试的各项功能有哪些?

云性能测试作为现代软件开发和部署过程中不可或缺的一环&#xff0c;为确保系统在各种条件下的高效运行提供了关键支持。本文将介绍云性能测试的各项功能&#xff0c;帮助您更好地了解其在软件开发生命周期中的重要性。 1. 负载测试 云性能测试的首要功能之一是负载测试。通过模…

Windows Server 2003 FTP服务器搭建

系列文章目录 目录 系列文章目录 文章目录 前言 一、FTP服务器是什么&#xff1f; 二、配置服务器 1.实验环境搭建 6)再次测试网络连通性 2.服务器搭建 1)控制面板中找到增加或删除程序打开 2)点击增加程序 3)安装FTP服务器 6)找到刚自己设定的路径下的文件夹,上传…

C语言——文件操作(看这一篇就够了)

1、为什么使用文件&#xff1f; 我们前面学习结构体&#xff0c;在写通讯录的时候会发现一个问题&#xff0c;我们向通讯录里面录入数据&#xff0c;当程序退出的时候&#xff0c;记录的数据也随之没有了&#xff0c;等下次我们在再调用通讯录时&#xff0c;又得重新录入数据&…

Java基于SpringBoot的学科竞赛系统,附源码,文档

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

ctfshow web71

开启环境&#xff1a; c?><?php $anew DirectoryIterator("glob:///*"); foreach($a as $f) {echo($f->__toString(). );} exit(0); ?> cinclude("/flagc.txt");exit();

网络和Linux网络_15(IO多路转接)reactor编程_服务器+相关笔试题

目录 1. reactor的服务器 1.1 Sock.hpp 1.2 加协议分割报文 1.3 序列化和反序列化 Protocol.hpp main.cc Epoll.hpp TcpServer.hpp 2. 相关笔试题 答案及解析 本篇完。 1. reactor的服务器 Log.hpp和以前一样&#xff0c;因为下面要写ET模式所以Sock.hpp加了一个把…

solr的原理是什么

1 Java程序里如果有无限for循环的代码导致CPU负载超高&#xff0c;如何排查&#xff1f; 排查Java程序中由于无限循环导致的CPU负载过高的问题&#xff0c;可以按照以下步骤进行&#xff1a; 资源监控&#xff1a; 使用系统命令行工具&#xff08;如Linux上的top或htop&#xf…

二、防御保护---防火墙基础知识篇

二、防御保护---防火墙基础知识篇 一、什么是防火墙二、防火墙的发展史1.包过滤防火墙(一个严格的规则表)2.应用代理防火墙(每个应用添加代理)3.状态检测防火墙(首次检查建立会话表)3.入侵检测系统(IDS)-----网络摄像头4.入侵防御系统(IPS)-----抵御2-7层已知威胁5.防病毒网关(…

Python---网络编程知识详解(学习笔记)基础部分

目录 一、IP地址 1.引入IP地址 2.ip地址的分类 2.1 IPv4的5种类别以及共有IP和私有IP 2.1.1 按照基本格式划分 2.1.2 按照功能用途来划分 2.1.2 特殊的P地址 一、IP地址 1.引入IP地址 特点&#xff1a;在逻辑上标记一台电脑&#xff08;唯一标记&#xff09; 作用&…

【Midjourney】如何自定义一套参数

使用Midjourney有时候会遇到需要调整某些参数的时候&#xff0c;例如宽高之类的&#xff1a; --hd --ar 7:4 而Midjourney中提供了一条指令用于自定义一套参数方便重复使用。 以下指令创建一个名为“mine”的选项&#xff0c;翻译过来就是 --hd --ar 7:4: 创建成功后会有类似…

【C++版】排序算法详解

目录 直接插入排序 希尔排序 选择排序 冒泡排序 堆排序 快速排序 hoare法 挖坑法 前后指针法 非递归版本 快速排序中的优化 归并排序 递归版本 非递归版本 计数排序 总结 直接插入排序 直接插入排序的思想是&#xff1a;把待排序的记录按其关键码值的大小逐个插入…

【EI会议征稿通知】第五届计算机信息和大数据应用国际学术会议(CIBDA 2024)

第五届计算机信息和大数据应用国际学术会议&#xff08;CIBDA 2024&#xff09; 2024 5th International Conference on Computer Information and Big Data Applications 第五届计算机信息和大数据应用国际学术会议&#xff08;CIBDA 2024&#xff09;将于2024年3月22-24日在…

运行VUE提示找不到模块validate-engines.js...

原来好好的&#xff0c;突然提示找不到模块validate-engines.js&#xff0c;CMD命令行输入npm -v不是内部或外部命令&#xff0c;node -v可以查看到版本号。 解决&#xff1a; 1. 卸载nodejs&#xff0c;重新下载安装文件&#xff1a;下载nodejs 2. 到目录&#xff1a;C:\Us…

深度学习与神经网络Pytorch版 3.2 线性回归从零开始实现 1.生成数据集

3.2 线性回归从零开始实现 目录 3.2 线性回归从零开始实现 一 &#xff0c;简介 1. 原理 2. 步骤 3. 优缺点 4. 应用场景 二 &#xff0c;代码展现 1. 生成数据集(完整代码) 2. 各个函数解析 2.1 torch.normal()函数 2.2 torch.matmul()函数 2.3 d2l.plt.scatter(…

18.通过telepresence调试部署在Kubernetes上的微服务

Telepresence简介 在微服务架构中,本地开发和调试往往是一项具有挑战性的任务。Telepresence 是一种强大的工具,使得开发者本地机器上开发微服务时能够与运行在 Kubernetes 集群中的其他服务无缝交互。本文将深入探讨 Telepresence 的架构、运行原理,并通过实际的案例演示其…

在mgre环境下配置ospf

实验规则如上图所示&#xff1a; 首先规划IP 配置缺省路由&#xff0c;使得公网全网可达 此处在r1上进行配置&#xff1a; 由此可以实现&#xff0c;公网已经全网可达&#xff1a; 其次&#xff0c;再分配 全连的MGRE网段&#xff0c;全连的MGRE网段每个路由器都是中心站点&…