一,Spring的简介和安装,深入理解IOC容器及测试

打印 上一主题 下一主题

主题 868|帖子 868|积分 2604

1) IOC/DI (IOC容器)
2) AOP面向切面编程
3) 声明式事务
官网地址:spring是一家公司-商业化运作。apache是一家基金会组织,接收社会的捐赠。

https://spring.io/
io表示开发者平台
 


 
 
 
1. Spring Framework

Spring 基础框架,可以视为 Spring 基础设施,基本上任何其他 Spring 项目都是以 Spring Framework 为基础的。
Spring5,基于jdk1.8 。
1.1 Spring Framework的优良特性

1 非侵入式:使用 Spring Framework 开发应用程序时,Spring 对应用程序本身的结构影响非常小。对领域模型(Java Bean)可以做到零污染;对功能性组件也只需要使用几个简单的注解进行标记,完全不会破坏原有结构,反而能将组件结构进一步简化。这就使得基于 Spring Framework 开发应用程序时结构清晰、简洁优雅。
2 控制反转:IOC——Inversion of Control,翻转资源获取方向。把自己创建资源、向环境索取资源变成环境将资源准备好,我们享受资源注入。
3 面向切面编程:AOP——Aspect Oriented Programming,在不修改源代码的基础上增强代码功能。
4 容器:Spring IOC 是一个容器,因为它包含并且管理组件对象的生命周期。组件享受到了容器化的管理,替程序员屏蔽了组件创建过程中的大量细节,极大的降低了使用门槛,大幅度提高了开发效率。
5 组件化:Spring 实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用 XML 和 Java 注解组合这些对象。这使得我们可以基于一个个功能明确、边界清晰的组件有条不紊的搭建超大型复杂应用系统。
6 声明式:很多以前需要编写代码才能实现的功能,现在只需要声明需求即可由框架代为实现。
7 一站式:在 IOC 和 AOP 的基础上可以整合各种企业应用的开源框架和优秀的第三方类库。而且 Spring 旗下的项目已经覆盖了广泛领域,很多方面的功能性需求可以在 Spring Framework 的基础上全部使用 Spring 来实现。
 
1.2 Spring Framework五大功能模块

 
2. IOC容器的概念

2.1 生活中的普通容器

 
 
 
 
普通容器只能用来存储,没有更多功能。
 
2.2 程序中的普通容器

变量,数组,集合
 
普通容器只能用来存储,没有更多功能。
 
2.3 生活中的复杂容器

 
政府管理我们的一生,生老病死都和政府有关。
 
4. IOC容器在Spring中的实现

Spring 的 IOC 容器就是 IOC 思想的一个落地的产品实现。IOC 容器中管理的组件也叫做 bean。在创建 bean 之前,首先需要创建 IOC 容器。Spring 提供了 IOC 容器的两种实现方式:
①BeanFactory
这是 IOC 容器的基本实现,是 Spring 内部使用的接口。面向 Spring 本身,不提供给开发人员使用。
 
②ApplicationContex -- 我们自己使用
BeanFactory 的子接口,提供了更多高级特性。面向 Spring 的使用者,几乎所有场合都使用 ApplicationContext 而不是底层的 BeanFactory。
 
所以,以后在 Spring 环境下看到一个类或接口的名称中包含 ApplicationContext,那基本就可以断定,这个类或接口与 IOC 容器有关。
 
③ApplicationContext的主要实现类
 
 
 
 
5. 基于XML管理bean

5.1 实验01[重要]创建bean,并根据id获取

5.1.1 目标

由 Spring 的 IOC 容器创建类的对象,并根据bean的id属性值来获取bean对象。
5.1.2 思路

 
 
 
 
自定义一个类IEmpService => EmpServiceImpl,这个类在Spring的配置文件中进行配置,然后用ClassPathXMLApplicationContext这个类去读取配置文件,然后根据配置文件中配置的东西,将这个对象建立出来。
 
5.1.3 创建maven项目,导入依赖

完整的pom文件


4.0.0
com.hy
mybatis001
0.0.1
war
 

UTF-8
UTF-8
UTF-8

 



org.springframework
spring-context
5.2.20.RELEASE

 


org.projectlombok
lombok
1.18.20

 


org.springframework
spring-test
5.2.20.RELEASE



junit
junit
4.12
test


 




org.apache.maven.plugins
maven-compiler-plugin

1.8
1.8

UTF-8





导入一个依赖,传递过来剩下的jar文件
 
 
 
 
 
 
 
5.1.4 EmpService -> EmpServiceImpl

package com.hy.service.impl;
 
import com.hy.service.EmpService;
 
public class EmpServiceImpl implements EmpService {
@Override
public void reg() {
System.out.println("用户注册");
}
}
 
 
1) 先导入spring的相关环境,其实就是导入pom文件jar包的坐标gav。
2) 创建spring的配置文件applicationContext.xml
      
 


 




这个bean没有属性,所以可以写成单标签
5.1.5 创建测试类

public class TestService {
// ApplicationContext就是我们的IOC容器
private ApplicationContext iocContainer = new ClassPathXmlApplicationContext("applicationContext.xml");
 
//实验01 [重要] 创建bean
//从IOC容器中获取已配置的bean
@Test
public void testEmpService() {
//通过bean的id属性的值得,获取这个bean对象
EmpService empService = (EmpService)iocContainer.getBean("empService");
empService.reg();
}
}
 
注意:Spring底层默认通过反射技术调用类的无参构造方法来创建类的对象。
5.1.6 无参构造方法的重要性,写一个有参的构造方法,测试

package com.hy.service.impl;
 
import com.hy.service.EmpService;
 
public class EmpServiceImpl implements EmpService {
 
public EmpServiceImpl(int age) {
}
 
@Override
public void reg() {
System.out.println("用户注册");
}
}
 
报错: 如果没有无参构造方法,则会抛出下面的异常:
 
 
 
 
所以对一个JavaBean来说,无参构造器和属性的getXxx()、setXxx()方法是必须存在的,特别是在框架中。
 
5.1.7 用IOC容器创建对象和自己建区别

 
 
被放入到容器当中,相当于加入了会员俱乐部
 
在Spring环境下能够享受到的所有福利,都必须通过 IOC 容器附加到组件类上,所以随着我们在 Spring 中学习的功能越来越多,IOC 容器创建的组件类的对象就会比自己 new 的对象 其功能强大的越来越多。
 
5.2 实验02[重要]创建bean,并根据class类型来获取

5.2.1 指定类型的 bean 唯一(只有一个)

 
5.2.2 测试

package com.hy.test;
 
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.hy.service.EmpService;
import com.hy.service.impl.EmpServiceImpl;
 
public class TestService2 {
// ApplicationContext就是我们的IOC容器
private ApplicationContext iocContainer = new ClassPathXmlApplicationContext("applicationContext.xml");
 
//实验02 [重要] 创建bean,并且根据类型获取bean对象
//从IOC容器中根据类型获取已配置的bean对象
@Test
public void testEmpService() {
// EmpService empService = iocContainer.getBean(EmpService.class);       //正确
EmpService empService = iocContainer.getBean(EmpServiceImpl.class);  //正确
empService.reg();  //用户注册
}
}
 
 
5.2.3 问题:如果配置了两个同样类型的bean对象,则报错,根据类型获取报错。



 



 


 
package com.hy.test;
 
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.hy.service.EmpService;
import com.hy.service.impl.EmpServiceImpl;
 
public class TestService2 {
// ApplicationContext就是我们的IOC容器
private ApplicationContext iocContainer = new ClassPathXmlApplicationContext("applicationContext.xml");
 
//实验02 [重要] 创建bean,并且根据类型获取bean对象
//如果容器中配置了同样类型的两个bean对象,
//从IOC容器中根据类型获取已配置的bean对象时,则报错。
@Test
public void testEmpService() {
// EmpService empService = iocContainer.getBean(EmpService.class);       //失败
EmpService empService = iocContainer.getBean(EmpServiceImpl.class);  //失败
}
}
 
 
 
 
 
 
 
 
5.2.4 总结

如果一个类实现了某个接口,根据接口类型可以获取 bean 吗?
可以,前提是bean唯一,如下的配置就不行。

 

 
如果一个接口有多个实现类,这些实现类都配置了 bean标签,根据接口类型可以获取 bean 吗?
不行,因为bean不唯一
 
根据类型来获取bean时,在满足bean唯一性的前提下,其实只是看:『对象 instanceof 指定的类型』的返回结果,只要返回的是true就可以认定为和类型匹配,能够获取到。
5.3 实验03[重要] 给bean的属性赋值:通过setXxx方法注入

5.3.1 首先,给EmpServiceImpl添加一个属性,提供setXxx和getXxx方法

package com.hy.service.impl;
 
import com.hy.service.EmpService;
 
public class EmpServiceImpl implements EmpService {
private String empStatus;
 
 
public String getEmpStatus() {
return empStatus;
}
 
 
public void setEmpStatus(String empStatus) {
this.empStatus = empStatus;
}
@Override
public void reg() {
System.out.println("用户注册");
}
}
 
5.3.2 在配置时给通过property标签给属性赋值

 
 
 
 
 





 
5.3.3 测试

package com.hy.test;
 
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.hy.service.impl.EmpServiceImpl;
 
public class TestService3 {
private ApplicationContext iocContainer = new ClassPathXmlApplicationContext("applicationContext.xml");
 
//实验03 [重要]
@Test
public void testEmpService() {
//通过bean的id属性的值得,获取这个bean对象
EmpServiceImpl empService3 = (EmpServiceImpl)iocContainer.getBean("empService3");
System.out.println(empService3.getEmpStatus());  //积极
}
}
 
5.4 实验04[重要] 引入外部已声明的bean


    
        
    
 
    
        
        
        
        
    
 
5.5 内部bean[重要]

 



           



 
5.6  引入外部属性文件[重要]



    
    
 
    
        
        
        
        
        
    
5.7 给bean的属性赋值:级联属性赋值(不重要,不怎么使用)

使用内部bean,给级联属性赋值。
 

    
 
        
        
            
            
        
 
        
        
    
5.8 通过构造方法,给bean属性赋值[不重要]


    
        
        
        
        
        
        
        
        
    
5.9 给bean的集合属性赋值[不重要]

private List nameList;  //标签不需要完全一致,一样可以赋值成功
private Map nameMap;
 

    
        
            
            
 
            
            
 
            
            
                member01
                member02
                member02
            
 
        
 
        
            
            
 
            
            
                张三2
                李四2
                王五2
            
        
    
5.10 自动装配 与 手动装配[了解]

所谓自动装配就是一个组件需要其他组件时,由 IOC 容器负责找到那个需要的组件,并装配进去。
    
    
    
 
    
    
    
    
        
        
    
@Test
public void testExperiment12() {
    HappyController happyController = iocContainer.getBean(HappyController.class);
    
    HappyService happyService = happyController.getHappyService();
    
    System.out.println("happyService = " + happyService);
}
5.11 bean的声明周期以及初始化
在无参构造方法打一个断点。
bean标签scope配置singleton时,bean的创建是在IOC容器初始化的时候,创建的,而不是在getBean的时候创建的。
bean标签scope配置prototype时,bean的创建实在调用getBean方法的时候创建的。
 
IOC容器关闭之前销毁bean对象。
 
 
 
 
 
 
 
这个接口总没有close方法在子接口中。
 
 
 
 
6,基于注解管理bean

和 XML 配置文件一样,注解本身并不能执行,注解本身仅仅只是做一个标记,具体的功能是框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作。
本质上:所有一切的操作都是Java代码来完成的,XML和注解只是告诉框架中的Java代码如何执行。
 
 
 
 
1) 首先根据所需要的组件类型到IOC容器中查找
能够找到唯一的bean:直接执行装配
如果完全找不到匹配这个类型的bean:装配失败
和所需类型匹配的bean不止一个
没有@Qualifier注解:根据@Autowired标记位置成员变量的变量名作为bean的id进行匹配
能够找到:执行装配
找不到:装配失败
使用@Qualifier注解:根据@Qualifier注解中指定的名称作为bean的id进行匹配
能够找到:执行装配
找不到:装配失败

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

徐锦洪

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表