栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

框架学习-2.Spring-1.认识Spring、IOC容器原理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

框架学习-2.Spring-1.认识Spring、IOC容器原理

文章目录

1. 认识Spring_IOC 总览Spring笔记思维导图:问题扩展与汇总:

1. Spring是什么,有什么优势

2.1 Spring概述2.2 Spring结构组成2.3 Spring优势 2. IoC 本质和作用

2.1 什么叫程序耦合,如果解耦2.2 IOC使用的工厂模式解耦原理

1)工厂模式解耦思路2)代码实现

工厂模式加工过程简化bean.properties用户只需传入bean的名字,通过工厂,获取bean对象 2.3 IOC控制反转思想 3. 使用 spring 的 IOC 解决程序耦合策略

3.1 基于 XML 的配置(入门案例)

1) 环境配置,导入spring依赖包2) 创建xml配置文件3)测试SpringIOC容器管理bean过程 3.2 Spring 基于 XML 的 IOC 细节

1)spring 中工厂常用IOC容器解析

常用IOC容器结构图BeanFactory 和 ApplicationContext区别 ApplicationContext常见三个实现类 2)IOC 中 bean 标签和管理对象细节

bean标签作用和基本属性bean作用范围和生命周期创建Bean的三种方式 3)spring 的依赖注入

依赖注入的概念 构造函数注入 set函数的注入注入复合/集合属性

1. 认识Spring_IOC 总览

参考狂神说MyBatis课程笔记

参考黑马程序员Spring课程笔记

Spring笔记思维导图:

思维导图笔记链接

问题扩展与汇总: 1. Spring是什么,有什么优势 2.1 Spring概述

Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架以 ==IoC(Inverse Of Control)和 AOP(Aspect Oriented Programming:面向切面编程)==为内核,提供了展现层 SpringMVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架

一句话概括:Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。

2.2 Spring结构组成

Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式 .

组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模
块的功能如下:

核心容器

核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory ,它是工厂模式的实现。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。 Spring 上下文

Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。 Spring AOP

通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能 , 集成到了 Spring
框架中。所以,可以很容易地使 Spring 框架管理任何支持 AOP的对象。Spring AOP 模块为基于Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。 Spring DAO

JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不
同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。 Spring ORM

Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包
括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。 Spring Web 模块

Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提
供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请
求以及将请求参数绑定到域对象的工作。 Spring MVC 框架

MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText
和 POI。 2.3 Spring优势

方便解耦,简化开发(IOC)

通过 Spring 提供的 IoC 容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造
成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。 AOP 编程的支持

通过 Spring 的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以
通过 AOP 轻松应付。 声明式事务的支持

可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务的管理,
提高开发效率和质量。 方便程序的测试

可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可
做的事情。 方便集成各种优秀框架

Spring 可以降低各种框架的使用难度,提供了对各种优秀框架( Struts、 Hibernate、 Hessian、 Quartz等)的直接支持。 降低 JavaEE API 的使用难度

Spring 对 JavaEE API(如 JDBC、 JavaMail、远程调用等)进行了薄薄的封装层,使这些 API 的
使用难度大为降低。 Java 源码是经典学习范例

Spring 的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对 Java 设计模式灵活运用以
及对 Java 技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。 2. IoC 本质和作用 2.1 什么叫程序耦合,如果解耦

程序的耦合

耦合:程序间的依赖关系包括:

类之间的依赖方法间的依赖

程序的解耦

实际开发中:应该做到:编译期不依赖,运行时才依赖。

解耦的思路

第一步:使用反射来创建对象,而避免使用new关键字

jdbc 时,是通过反射来注册驱动的,代码如下:
Class.forName(“com.mysql.jdbc.Driver”);
而不是 DriverManager.registerDriver(new com.mysql.jdbc.Driver());这样好处是只依赖字符串,而不是依赖具体的驱动类
此时就算删除 mysql 的驱动 jar 包,依然可以编译,运行不行 。

第二步:通过==读取配置文件来获取要创建的对象全限定类名==

mysql 驱动的全限定类名字符串是在 java 类中写死的,一旦要改还是要修改
源码。解决这个问题的思路就是,使用配置文件配置

2.2 IOC使用的工厂模式解耦原理 1)工厂模式解耦思路

在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候, 让一个类中的方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。那么,这个读取配置文件, 创建和获取三层对象的类就是工厂 2)代码实现 工厂模式加工过程简化

1.读取扫描配置文件,提取配置文件中的key,和对应的value:类的全限定类名

//根据key获取value
String beanPath = props.getProperty(key); 2.通过全限定类名进行反射创建对象

//反射创建对象
Object value = Class.forName(beanPath).newInstance(); 3.将这些对象放进map容器中,这个容器就相当于工厂

//定义一个Map,用于存放我们要创建的对象。我们把它称之为容器
private static Map beans;//把key和value存入容器中
beans.put(key,value);

public class BeanFactory {
    //定义一个Properties对象
    private static Properties props;

    //定义一个Map,用于存放我们要创建的对象。我们把它称之为容器
    private static Map beans;

    //使用静态代码块为Properties对象赋值
    static {
        try {
            //实例化对象
            props = new Properties();
            //获取properties文件的流对象(扫描配置文件)
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);
            //实例化容器
            beans = new HashMap();
            //取出配置文件中所有的Key
            Enumeration keys = props.keys();
            //遍历枚举,根据key,权限类名实例化对应的对象
            while (keys.hasMoreElements()){
                //取出每个Key
                String key = keys.nextElement().toString();
                //根据key获取value
                String beanPath = props.getProperty(key);
                //反射创建对象
                Object value = Class.forName(beanPath).newInstance();
                //把key和value存入容器中
                beans.put(key,value);
            }
        }catch(Exception e){
            throw new ExceptionInInitializerError("初始化properties失败!");
        }
    }
}

bean.properties
accountService=com.itheima.service.impl.AccountServiceImpl
accountDao=com.itheima.dao.impl.AccountDaoImpl
用户只需传入bean的名字,通过工厂,获取bean对象
    public static Object getBean(String beanName){
        return beans.get(beanName);
    }
2.3 IOC控制反转思想

对象创建的控制权反转,由原来的主体去主动创建控制对象,改为交给工厂,让工厂去控制创建对象,主体需要的时候,只需向工厂要就行,与多态思想类似,多态是用户需要什么对象,交给接口,父类的引用会自动指向子类的对象,接口会返回给需要的资源给用户明确 ioc 的作用:
削减计算机程序的耦合(解除我们代码中的依赖关系)。

原来:
我们在获取对象时,都是采用 new 的方式。 是主动的

​ 现在:
​ 我们获取对象时,同时跟工厂要,有工厂为我们查找或者创建对象。 是被动的。

3. 使用 spring 的 IOC 解决程序耦合策略 3.1 基于 XML 的配置(入门案例) 1) 环境配置,导入spring依赖包

        
            org.springframework
            spring-context
            5.0.2.RELEASE
        

2) 创建xml配置文件

在类的根路径下创建xml配置文件,一般在sources目录下

给配置文件导入约束




让Spring管理资源,配置service和dao层需要的bean

 
 

 
3)测试SpringIOC容器管理bean过程

Spring容器会扫描配置文件,创建bean,装入IOC容器中用户可以根据配置文件id,可以向容器中获取需要的bean

 
    public static void main(String[] args) {
        //1.获取核心容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        
//        ApplicationContext ac = new FileSystemXmlApplicationContext("C:\Users\zhy\Desktop\bean.xml");
        
        //2.根据id的bean名称获取Bean对象
        IAccountService as  = (IAccountService)ac.getBean("accountService");
        IAccountDao adao = ac.getBean("accountDao",IAccountDao.class);

        System.out.println(as); // 打印出获取的bean对象
        System.out.println(adao);

        //--------BeanFactory----------
//        Resource resource = new ClassPathResource("bean.xml");
//        BeanFactory factory = new XmlBeanFactory(resource);
//        IAccountService as  = (IAccountService)factory.getBean("accountService");
//        System.out.println(as);
    }
3.2 Spring 基于 XML 的 IOC 细节 1)spring 中工厂常用IOC容器解析 常用IOC容器结构图 BeanFactory 和 ApplicationContext区别

BeanFactory 才是 Spring 容器中的顶层接口。
ApplicationContext 是它的子接口。BeanFactory 和 ApplicationContext 的区别:

创建对象的时间点不一样

ApplicationContext:它在构建核心容器时,创建对象采取的策略是采用立即加载的方式。
也就是说,只要==一读取完配置文件马上就创建配置文件中配置的对象==。BeanFactory: 它在构建核心容器时,创建对象采取的策略是采用延迟加载的方式。
也就是说,什么时候根据id获取对象了,什么时候才真正的创建对象。 默认创建对象的单例多例不同

ApplicationContext:默认是单例模式,也可以设置成多例,故一般用这个接口

因为本例中service和dao层的对象都没有成员变量,不设计线程安全问题,单例模式效率高 BeanFactory:默认是多例模式 ApplicationContext常见三个实现类

ClassPathXmlApplicationContext:

它是从类的根路径下加载配置文件 推荐使用这种 FileSystemXmlApplicationContext:

它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。 AnnotationConfigApplicationContext:

当我们使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。 2)IOC 中 bean 标签和管理对象细节 bean标签作用和基本属性

作用:

用于==配置对象让 spring 来创建==的。默认情况下它调用的是类中的无参构造函数。如果没有无参构造函数则不能创建成功。

属性:

id: 给对象在容器中提供一个唯一标识。用于获取对象。class: 指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数。scope: 指定对象的作用范围。

singleton :默认值,单例的.prototype :多例的.request : WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中.session :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中.global session 作用于集群环境的会话范围(全局会话范围),

当不是集群环境时,它就是session init-method: 指定类中的初始化方法名称。destroy-method: 指定类中销毁方法名称。 bean作用范围和生命周期

单例对象: scope="singleton"

一个应用只有一个对象的实例。它的作用范围就是整个引用。生命周期:

对象出生:当应用加载,创建容器时,对象就被创建了。对象活着:只要容器在,对象一直活着。对象死亡:当应用卸载,销毁容器时,对象就被销毁了。

多例对象: scope="prototype"

每次访问对象时,都会重新创建对象实例。生命周期:

对象出生:当使用对象时,创建新的对象实例。对象活着:只要对象在使用中,就一直活着。对象死亡:当对象长时间不用时,被 java 的垃圾回收器回收了。

实例:

public class AccountServiceImpl implements IAccountService {
    public AccountServiceImpl(){
        System.out.println("对象创建了");
    }
    
    public void  saveAccount(){
        System.out.println("service中的saveAccount方法执行了。。。");
    }

    public void  init(){
        System.out.println("对象初始化了。。。");
    }
    public void  destroy(){
        System.out.println("对象销毁了。。。");
    }

}

创建Bean的三种方式

第一种方式:使用默认构造函数创建。

在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时。采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。


第二种方式: spring 管理实例工厂-使用实例工厂的方法创建对象

虚拟一个实例工厂,假设是外在jar包中的类

public class InstanceFactory {
	// 工厂类创建对象AccountServiceImpl
    public IAccountService getAccountService(){
        return new AccountServiceImpl();
    }
}

先把工厂的创建交给 SpringIOC 来管理一般用于处理引入的jar包中的类。

然后在使用工厂的 bean ,来调用里面的方法来创建需要的对象

factory-bean 属性:用于指定实例工厂 bean 的 id。

factory-method 属性:用于指定实例工厂中创建对象的方法



第三种方式: spring 管理静态工厂-使用静态工厂的方法创建对象

模拟一个工厂类

public class StaticFactory {

    public static IAccountService getAccountService(){

        return new AccountServiceImpl();
    }
}

使用 StaticFactory 类中的静态方法 getAccountService 创建对象,并存入 spring 容器

id 属性:指定 要创建bean 的 id,用于从容器中获取

class 属性:指定静态工厂的全限定类名

factory-method 属性:指定生产对象的静态方法


3)spring 的依赖注入 依赖注入的概念

依赖注入: Dependency Injection

它是 spring 框架核心 ioc 的具体实现。 依赖关系的管理:

通过控制反转, 把对象的创建交给了 spring来管理对象之间的依赖关系以后都交给spring来维护在当前类需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明 依赖关系的维护:

就称之为依赖注入。例如处理业务层和持久层的依赖关系,只需配置文件中说明好,框架会自动将持久层对象传入业务层 依赖注入种类:能注入的数据:有三类

基本类型和String其他bean类型(在配置文件中或者注解配置过的bean)复杂类型/集合类型 注入的方式:有三种

第一种:使用构造函数提供第二种:使用set方法提供第三种:使用注解提供 构造函数注入

就是使用类中的构造函数,给成员变量赋值。注意,赋值的操作不是我们自己做的,而是==通过配置的方式,让 spring 框架来为我们注入==

先在需要注入的bean中添加有参构造函数

public class AccountServiceImpl implements IAccountService {

    //如果是经常变化的数据,并不适用于注入的方式
    private String name;
    private Integer age;
    private Date birthday;

    public AccountServiceImpl(String name,Integer age,Date birthday){
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

    public void  saveAccount(){
        System.out.println("service中的saveAccount方法执行了...+name+","+age+","+birthday);
    }
}

在配置文件中注入信息

使用构造函数的方式,给 service 中的属性传值

要求:

类中需要提供一个对应参数列表的构造函数。

涉及的标签:

constructor-arg

属性:

index:指定参数在构造函数参数列表的索引位置

type:指定参数在构造函数中的数据类型

name:指定参数在构造函数中的名称 用这个找给谁赋值

上面三个都是找给谁赋值,下面两个指的是赋什么值的

value:它能赋的值是基本数据类型和 String 类型

ref:它能赋的值是其他 bean 类型,即IOC容器中的bean

优势:

在获取bean对象时可以传入参数,注入数据是必须的操作,否则对象无法创建成功。

弊端:

改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。


    
    
    




set函数的注入

就是在类中提供需要注入成员的 set 方法通过配置文件给 bean 中的属性传值:使用 set 方法的方式

bean类中添加set方法

**
 * 账户的业务层实现类
 */
public class AccountServiceImpl2 implements IAccountService {

    //如果是经常变化的数据,并不适用于注入的方式
    private String name;
    private Integer age;
    private Date birthday;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public void  saveAccount(){
        System.out.println("service中的saveAccount方法执行了。。。"+name+","+age+","+birthday);
    }
}

在配置文件中用set注入信息

 

也可以用property名称标签


    
    
    



也可以用p名称标签,本质与set函数注入方式一致




注入复合/集合属性

就是给类中的集合成员传值,它用的也是set方法注入的方式**,只不过变量的数据类型都是集合**。例如注入String[],List,Set,Map,Properties。

bean中添加set方法

public class AccountServiceImpl3 implements IAccountService {

    private String[] myStrs;
    private List myList;
    private Set mySet;
    private Map myMap;
    private Properties myProps;

    public void setMyStrs(String[] myStrs) {
        this.myStrs = myStrs;
    }

    public void setMyList(List myList) {
        this.myList = myList;
    }

    public void setMySet(Set mySet) {
        this.mySet = mySet;
    }

    public void setMyMap(Map myMap) {
        this.myMap = myMap;
    }

    public void setMyProps(Properties myProps) {
        this.myProps = myProps;
    }

    public void  saveAccount(){
        System.out.println(Arrays.toString(myStrs));
        System.out.println(myList);
        System.out.println(mySet);
        System.out.println(myMap);
        System.out.println(myProps);
    }
}

配置文件中用set注入信息

 

    
	
    
        
            AAA
            BBB
            CCC
        
    

    
    
        
            AAA
            BBB
            CCC
        
    

    
    
        
            AAA
            BBB
            CCC
        
    

    
    
        
            ccc
            ddd
        
    

    
    
        
            
            
                BBB
            
        
    

结构测试:

[AAA, BBB, CCC]
[AAA, BBB, CCC]
[AAA, BBB, CCC]
{testD=ddd, testC=ccc}
{testA=aaa, testB=BBB}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/726189.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号