Spring 优点:
- 方便解耦,简化开发。将所有对象创建和依赖关系维护交给 Spring 管理(IOC 的作用)
- AOP 切面编程的支持。方便的实现对程序进行权限的拦截、运行监控等功能(可扩展性)
- 声明式事务的支持。只需通过配置就可以完成对事务的管理,无需手动编程
- 方便程序测试。Spring 对 junit4 支持,可以通过注解方便测试 Spring 程序
- 方便集成各种优秀框架
- 降低 API 的使用难度
IOC:控制权反转
-
作用:
- 将创建对象的过程交给 Spring 框架进行管理
- 降低代码的耦合度。利用 IOC 容器进行控制
- 一个程序失控后不会影响其他程序的运转
-
使用:
-
创建 Maven 项目,导入依赖:
<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>
-
项目基本结构:
-
编写 Spring 核心的配置文件:
- 在 resources 下边创建 application.xml 文件
-
xml 方式创建对象:
<!--IOC容器管理的bean--> <!--利用spring工厂创建对象--> <!--id: 唯一表示符 -> 对象名称 --> <!--class: 类的全路径--> <bean id="userService" class="com.qcby.spring.service.impl.UserServiceImpl" />
-
测试类:
public class TestIOC { //传统调用 @Test public void run(){ UserServiceImpl userService = new UserServiceImpl(); userService.sayHello(); } //Spring 创建对象写法 @Test public void run(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml"); UserServiceImpl userService = (UserServiceImpl) applicationContext.getBean("userService"); userService.sayHello(); } }
-
-
IOC 技术总结:
- ApplicationContext 接口:工厂的接口,使用接口可以获取到具体的 Bean 对象
- 该接口下有两个实现类,SpringCould 配置中心:
- ClassPathXmlApplicationContext:加载类路径下的 Spring 配置文件
- FileSystemXmlApplicationContext:加载本地磁盘下的 Spring 配置文件
Spring 对对象的管理:
- 分类:
- 基于配置文件的方式:
- 创建对象
- 注入属性
- 基于注解方式实现:
- 创建对象
- 注入属性
- 基于配置文件的方式:
- Spring 框架的 Bean 管理的配置文件的方式:
- ID 属性:
- 给 Bean 起个名字,在约束中采用 ID 的唯一约束
- 取值要求:必须以字母开始,可以使用字母、数字、下划线、句号、冒号。不能出现特殊字符
- class 属性:Bean 对象的全路径
- scope 属性:scope 属性代表 Bean 的作用范围
- singleton 属性:表示单例 (默认值),最常用的方式
- prototype 属性:应用在 Web 项目中,同一个 HTTP Session 共享一个 Bean
- ID 属性:
- Bean 对象的创建和销毁的两个属性配置:
- 说明:
- Spring 初始化 Bean 或销毁 Bean 时,有时需要做一些处理工作,因此 spring 可以在创建和拆卸 bean 的时候调用 bean 的两个声明周期方法
- init-method 属性:当 bean 被加载到容器的时候用 init-method 属性指定的方法
- destory-method 属性:当 bean 从容器中删除的时候用 destory-method 属性指定的方法
- 说明:
- 实例化 Bean 对象的三种方法:
-
默认无参数的构造方法(默认方法,基本使用)
<bean id="userService" class="com.qcby.spring.service.impl.UserServiceImpl" > <property name="name" value="张三"/> <property name="age" value="44"/> </bean>
-
静态工厂实例化方法:
/** * 静态工厂方式 */ public class StaticFactory { //静态工厂方式 public static UserService creatUs(){ System.out.println("静态工厂方式创建 UserServiceImpl对象"); //业务逻辑 + 权限校验 return new UserServiceImpl(); } } //配置文件 <bean id="us" class="com.qcby.spring.factory.StaticFactory" factory-method="creatUs"></bean>
-
动态工厂实例化方法:
/** * 动态工厂实例化方式 */ public class Dfactory { public UserService craeatUs(){ System.out.println("动态实例化工厂的方式"); //业务逻辑 + 权限校验 return new UserServiceImpl(); } } //配置文件 <bean id="dfactory" class="com.qcby.spring.factory.Dfactory"></bean> <bean id="us" factory-bean="dfactory" factory-method="craeatUs"></bean>
-
DI:依赖注入
-
IOC 和 DI 的概念:
- IOC:Inverse of Control,控制权反转,将对象创建权反转给 Spring
- DI:Dependency Injection,依赖注入,在 Spring 框架负责创建 Bean 对象时,动态的将依赖对象注入到 Bean 组件中
-
set 方法注入属性:
-
<property name="" value = "" />
-
注意:给类、集合、列表和 map 集合,property 类型赋值的方式
-
实体类:
public class User { private String name; private Integer age; private Demo demo; private String[] strs; List<String> list; Map<String,String> map; @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", demo=" + demo + ", strs=" + Arrays.toString(strs) + ", list=" + list + ", map=" + map + '}'; } //get set 方法
-
注入属性:
<!--IOC容器管理的bean--> <!--id:唯一表示符--> <!--class:类的全路径--> <bean id="demo" class="com.spring.service.Demo"/> <bean id="uesr" class="com.spring.service.User"> <property name="name" value="张三"/> <property name="age" value="18"/> <!-- 给对象赋值 –> 用 ref 属性 首先要有这个对象--> <property name="demo" ref="demo"/> <!-- 给数组赋值 利用 <array></array>--> <property name="strs"> <array> <value>熊大</value> <value>熊二</value> </array> </property> <!--给list列表赋值利用 <list></list>--> <property name="list"> <list> <value>张胜男</value> <value>理事长</value> </list> </property> <!--给 map 赋值 <map> <emtry key = "" value = "" /> </map>--> <property name="map"> <map> <entry key="张三" value="河北"/> <entry key="李思思" value="北京"/> </map> </property> </bean> </beans>
-
-
利用构造器注入属性:
-
<constructor-arg name = '' " value = " ">
-
实体类:
public class User { private String name; private Integer age; private Demo demo; private String[] strs; List<String> list; Map<String,String> map; public User(String name, Integer age, Demo demo, String[] strs, List<String> list, Map<String, String> map) { this.name = name; this.age = age; this.demo = demo; this.strs = strs; this.list = list; this.map = map; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", demo=" + demo + ", strs=" + Arrays.toString(strs) + ", list=" + list + ", map=" + map + '}'; } }
-
注入数据:
<!--IOC容器管理的bean--> <!--id:唯一表示符--> <!--class:类的全路径--> <bean id="demo" class="com.spring.service.Demo"/> <bean id="user" class="com.spring.service.User"> <constructor-arg name="name" value="张胜男"/> <constructor-arg name="age" value="18"/> <!--给对象赋值 利用 ref --> <constructor-arg name="demo" ref="demo"/> <!--给数组赋值--> <constructor-arg name="strs"> <array> <value>张思思</value> <value>王菲</value> <value>李思琪</value> </array> </constructor-arg> <!--给 list 列表赋值--> <constructor-arg name="list"> <list> <value>1111</value> <value>aaaa</value> </list> </constructor-arg> <!--给 map 集合赋值 利用 entry--> <constructor-arg name="map"> <map> <entry key="111" value="sss"/> <entry key="222" value="aaa"/> </map> </constructor-arg> <!--给 property 类型赋值 内部是 key value 形式 --> <constructor-arg name = "properties"> <props> <prop key = "username">root</prop> <prop key = "age">18</prop> </props> </constructor-arg> </bean> </beans>
-
注解创建对象:
-
配置扫描固定的包:
-
作用:把当前类使用 IOC 容器进行管理,如果没有指定名称,默认使用类名,首字母小写方式命名
//扫描固定包下的文件 <context:component-scan base-package="com.spring.service"/>
-
-
bean 管理类常用注解:
-
@Component():普通的类
-
@Controller():表现层
-
@Service():业务层
-
@Repository():持久层
@Component(value = "user") //@Controller() //@Service() //@Repository() public class user{ @Value("zhang") //--->一般针对于包装类和基本数据类型 private String name; @Value("男") private Integer age; @Value("男") private String sex; @Autowired() //----> 对对象类型直接注入 private Demo demo; }
-
-
依赖注入常用的注解:
- @Value():用于注入基本类型数据
- @Autowired():用于注入引用类型
- @Qualifier():和 @Autowired 一起使用,强制使用名称注入
- @Resource():一般不用( jdk 提供),按名称注入对象
- @Scope:声明周期注解
- singleton(默认值):单实例
- prototype:多例
-
初始化方法和销毁方法注解:
- @PostConstrust 相当于 init-method
- @PreDestroy 相当于 destroy-method
-
不用配置文件,用注解赋值方式:
-
实体类配置:
@Configuration //标明当前类为配置类 @ComponentScan(value = "com.spring.service") //扫描固定的包 public class User { @Value("zhang") //--->一般针对于包装类和基本数据类型 private String name; @Value("18") private Integer age; @Value("男") private String sex; @Autowired() //----> 对对象类型直接注入 private Demo demo; }
-
测试类获取:
public class Test { public static void main(String[] args) { ApplicationContext ac = new AnnotationConfigApplicationContext(User.class); User user = (User) ac.getBean("user"); System.out.println(user.toString()); } }
-
多配置文件形式:
- 在加载配置文件时,后多加自己需要的配置文件:
- 在一个配置文件中利用 <import resource = " " /> 引入另一个配置文件:
Spring 框架开发方式:
- 需求:编写 service 和 dao 的类
- 技术选择:持久层使用 JDBC 的程序,连接池是 Druild 连接池,创建 maven 工程,导入 jar 包
- 开发流程:
-
导入相关 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 类:
public class Account implements Serializable { public 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 + ", nane='" + name + '\'' + ", money=" + money + '}'; } }
-
编写 AccountDao 接口实现类:
public class AuccountDaoImpl implements AccountDao { //注入连接池对象 private DataSource dataSource; public void setDataSource(DataSource dataSource){ this.dataSource = dataSource; } /** * 查询所有的数据 * @return */ @Override public List<Account> finAll() { 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")); } }catch (Exception e){ e.printStackTrace(); }finally { try{ connection.close(); stmt.close(); rs.close(); }catch (Exception e){ e.printStackTrace(); } } return list; } }
-
编写配置文件:
<!--配置连接池--> <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.spring.service.Impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> </bean> <bean id="accountDao" class="com.spring.dao.Impl.AuccountDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean>
-
编写测试程序:
public class Test { @org.junit.Test public void run(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("aaplication.xml"); AccountService accountService = (AccountService) applicationContext.getBean("accountService"); List<Account> list = accountService.findAll(); for (Account account : list){ System.out.println(account); } } }
-
IOC纯注解方式:
-
概述:
- 纯注解方式是微服务架构开发的主要方式
- 替换掉所有的配置文件,但是需要写配置类
-
常用的注解:
-
@Configuration:声明该类为配置类
-
@ComponentScan:扫描具体包结构
-
@Import:用于导入其他配置类
//Spring 配置类,替换掉 applicationContext.xml //声明当前是配置类 @Configuration //扫描指定的包结构 @ComponentScan("com.qcby.spring") //导入其他配置类 @Import(value = SpringConfig2.class) public class SpringConfig { } @Component public class SpringConfig2 { }
-
@Bean:只能写在方法上,表明使用此方法创建一个对象,对象创建完成保存到 IOC 容器中
@Bean(name="dataSource") public DataSource creatDataSource(){ DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///community"); dataSource.setUsername("root"); dataSource.setPassword("root"); return dataSource; }
-
-
案例:
-
编写实体类:
@Component public class Order { @Value("北京") private String address; @Override public String toString() { return "Order{" + "address='" + address + '\'' + '}'; } }
-
编写配置类:
//Spring 配置类,替换掉 applicationContext.xml //声明当前是配置类 @Configuration //扫描指定的包结构 @ComponentScan("com.qcby.spring") public class SpringConfig { }
-
编写测试方法:
@Test public void run1(){ //创建工厂,加载配置类 ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class); //获取对象 Order order = (Order) ac.getBean("order"); System.out.println(order); }
-
Spring 框架整合 JUnit 单元测试:
-
导入依赖:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.2.RELEASE</version> <scope>test</scope> </dependency>
-
配置文件形式:
-
编写类和方法,并把该类交给 IOC 容器进行管理:
public class User { public void sayHello(){ System.out.println("Hello"); } }
-
编写配置文件:
<?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.qcby.spring.pojo.User"></bean> </beans>
-
编写测试方法
//Spring整合单测试 @RunWith(value = SpringJUnit4ClassRunner.class) @ContextConfiguration(value = "classpath:application_test.xml") public class Demo { //自动注入 @Autowired private User user; @Test public void run1(){ user.sayHello(); } }
-
-
纯注解方式整合单元测试:
-
编写类和方法:
@Component public class Customer { public void save(){ System.out.println("保存客户"); } }
-
编写配置方法:
//声明配置类 @Configuration //扫描包 @ComponentScan(value = "com.qcby.spring") public class SpringConfig3 { }
-
编写测试方法:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SpringConfig3.class) public class Demo2 { //注入对象 @Autowired private Customer customer; //测试 @Test public void run(){ customer.save(); } }
-