Spring 的控制反转/依赖注入

第一章 Spring 的控制反转/依赖注入

回顾

增删改查。

课前测:

本章内容

spring:春天 IOC:将创建对象的权力交给 spring 核心容器去控制。工厂模式

BeanFactory: 懒汉

ApplicationContext: 饿汉

< bean id="" name="" class="" scope="" >

getBean的三种方式: id 类型 id+类型

创建对象的三种方式:1.默认使用无参构造创建 2.使用工厂静态方 3.实例方法

生命周期:

​ 单例对象:关闭容器时,销毁对象

​ 多利对象:GC垃圾回收机制 (守护线程)

第一节:Spring 春天

控制:对象的创建。

控制反转:将创建对象的权力交给 spring 核心容器去控制。

1.简介

框架:半成品软件,由美国技术大拿开发.

spring 生态圈,spring全家桶(spring MVC boot cloud data security)

SSM : spring springMVC Mybatis

srpringboot cloud

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

MVC model view controller=====>三层架构 service

模型(实体和dao) 视图(jsp) 控制器(servlet)—>

三层架构:

​ 展现层web:controller(页面的跳转),jsp(页面)

​ 持久层:dao (数据操作)

​ 业务层:service (业务逻辑)

2.Spring的发展历程

1997 年 IBM 提出了 EJB 的思想

1998 年,SUN 制定开发标准规范 EJB1.0

1999 年,EJB1.1 发布

2001 年,EJB2.0 发布

2003 年,EJB2.1 发布

2006 年,EJB3.0 发布

Rod Johnson(spring 之父)

在这里插入图片描述

Expert One-to-One J2EE Design and Development(2002)

阐述了 J2EE 使用 EJB 开发设计的优点及解决方案

Expert One-to-One J2EE Development without EJB(2004)

阐述了 J2EE 开发不使用 EJB 的解决方式(Spring 雏形)

2017 年 9 月份发布了 spring 的最新版本 spring 5.0 通用版(GA)

3. Spring的优点

servlet调用dao

BookDao bookdao = new BookDaoImpl();

  • 方便解耦,简化开发

通过 Spring 提供的 IoC 容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造

成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可

以更专注于上层的应用。

  • AOP 编程的支持

​ 通过 Spring 的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以

通过 AOP 轻松应付。

  • 声明式事务的支持

​ 可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务的管理,

提高开发效率和质量。

  • 方便程序的测试

​ 可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可

做的事情。

  • 方便集成各种优秀框架

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

微软(邪教) J++ SunPK(正教人多,分散,谁都听谁的,Spring第三方框架,IBM HP EMC 通用 宇通等)

Spring崛起把微软干趴下了

  • 降低 JavaEE API 的使用难度

Spring 对 JavaEE API(如 JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些 API 的

使用难度大为降低。

  • Spring 源码是经典学习范例

​ Spring 的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对 Java 设计模式灵活运用以

及对 Java 技术的高深造诣。它的源代码无疑是 Java 技术的最佳实践的范例。

4.Spring的体系结构

在这里插入图片描述

javaBean

模块

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

ORM 持久层框架

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bRxjDwbz-1645885880916)(assets/HemWeNoCPcQvsarJ.png!thumbnail)]

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

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

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

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

  • 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。

Spring 框架的功能可以用在任何 J2EE 服务器中,大多数功能也适用于不受管理的环境。Spring 的核心要点是:支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同 J2EE 环境 (Web 或 EJB)、独立应用程序、测试环境之间重用。

第二节:Spring的IOC控制反转

1.为什么要用 Spring

目的:降低耦合:对象与对象之间的耦合。

举个栗子:

在这里插入图片描述

如何解决这个问题呢?使用工厂模式解决。
在这里插入图片描述

代码改过后并没有完成我们的目的。此时如果将Food变成了Food1还是要一个一个修改。

如何解决?使用接口的多态。
在这里插入图片描述

2.程序的耦合 (课下自己看)

耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性)。耦合性存在于各个领域,而非软件设计中独有的,但是我们只讨论软件工程中的耦合。在软件工程中,耦合指的就是就是对象之间的依赖性。对象之间的耦合越高,维护成本越高。因此对象的设计应使类和构件之间的耦合最小。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个准则就是高内聚低耦合。

它有如下分类:

(1)内容耦合。当一个模块直接修改或操作另一个模块的数据时,或一个模块不通过正常入口而转入另一个模块时,这样的耦合被称为内容耦合。内容耦合是最高程度的耦合,应该避免使用之。

(2)公共耦合。两个或两个以上的模块共同引用一个全局数据项,这种耦合被称为公共耦合。在具有大量公共耦合的结构中,确定究竟是哪个模块给全局变量赋了一个特定的值是十分困难的。

(3) 外部耦合 。一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息,则称之为外部耦合。

(4) 控制耦合 。一个模块通过接口向另一个模块传递一个控制信号,接受信号的模块根据信号值而进行适当的动作,这种耦合被称为控制耦合。

(5)标记耦合 。若一个模块 A 通过接口向两个模块 B 和 C 传递一个公共参数,那么称模块 B 和 C 之间存在一个标记耦合。

(6) 数据耦合。模块之间通过参数来传递数据,那么被称为数据耦合。数据耦合是最低的一种耦合形式,系统中一般都存在这种类型的耦合,因为为了完成一些有意义的功能,往往需要将某些模块的输出数据作为另一些模块的输入数据。

(7) 非直接耦合 。两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的。

**总结:**耦合是影响软件复杂程度和设计质量的一个重要因素,在设计上我们应采用以下原则:如果模块间必须存在耦合,就尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,尽量避免使用内容耦合。

内聚与耦合:内聚标志一个模块内各个元素彼此结合的紧密程度,它是信息隐蔽和局部化概念的自然扩展。内聚是从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做一件事。它描述的是模块内的功能联系。耦合是软件结构中各模块之间相互连接的一种度量,耦合强弱取决于模块间接口的复杂程度、进入或访问一个模块的点以及通过接口的数据。 程序讲究的是低耦合,高内聚。就是同一个模块内的各个元素之间要高度紧密,但是各个模块之间的相互依存度却要不那么紧密。内聚和耦合是密切相关的,同其他模块存在高耦合的模块意味着低内聚,而高内聚的模块意味着该模块同其他模块之间是低耦合。在进行软件设计时,应力争做到高内聚,低耦合

3. 解决方案(IOC控制反转)

什么是IOC ?

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。使用对象的时候不再是我们直接new,而是将创建对象的权利交给框架中的核心容器,需要使用对象的时候直接从容器中获取。

IoC的思想早就出现了,但是没有一个具体的实现,大家都是各自根据这个思想去写代码(自己去创建工厂)。后来有一个大师 Rod Johnson(Spring Framework创始人,著名作者。 Rod在悉尼大学不仅获得了计算机学位,同时还获得了音乐学位。更令人吃惊的是在回到软件开发领域之前,他还获得了音乐学的博士学位。),写了一个框架,将IoC思想具体的实现了,这个框架后来起了个名字叫做 Spring。(因为在这之前 大家都是用hibernate这个框架,这个框架中文名字叫做冬眠,并且这个框架比较笨重,耦合比较高。Rod Johnson写的框架就是用来解决类似于hibernate高耦合的问题 ,所以他将自己框架的名字命名为 Spring 告诉全世界 冬天过去了 春天来了)。

在这里插入图片描述

第三节:spring项目的搭建

1.1 下载jar包

官网:http://spring.io/

下载地址:https://repo.springsource.org/libs-release-local/org/springframework/spring

现在Spring–>生态圈(全家桶)

在这里插入图片描述

在这里插入图片描述

解压:

在这里插入图片描述

(Spring 目录结构:)

* docs :API 和开发规范。

* libs :jar 包和源码。

*schema :约束。

创建项目并导入jar包

image-20201218004147055
1.2 配置bean.xml文件
image-20201218004738988 ![在这里插入图片描述](https://img-blog.csdnimg.cn/1af10999eeef48a4950bb75ae324222a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAdGVhX3llYXI=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
1.3 编写测试代码并运行

测试类中可以通过两种方式获取Bean对象的创建。

参考以下,两个接口的区别:

输出结果,可以观察到对象的创建,方法的调用

2.spring对Bean对象的管理细节

spring的核心组件:BeanFactory 接口 和 ApplicationContext接口

两者功能类似。

2.1 ApplicationContext 和BeanFactory 两个接口的区别

spring工厂中类的结构图。

image-20201219001254187

BeanFactory接口

​ Spring容器顶层接口:获取Bean对象;管理类和类之间的关系(依赖关系)BeanFactory由org.springframework.beans.factory.BeanFactory接口定义 BeanFactory是工厂模式(Factory pattern)的实现,是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

BeanFactory接口包含以下基本方法——ApplicationContext肯定都有,因为他是子接口,加强版

boolean  containsBean(String beanName) 判断工厂中是否包含给定名称的bean定义,若有则返回true。

Object  getBean(String  str)返回给定名称注册的bean实例。根据bean的配置情况,如果是singleton模式将返回一个共享实例,否则将返回一个新建的实例,如果没有找到指定bean,该方法可能会抛出异常。

Object  getBean(String, Class) 返回以给定名称注册的bean实例,并转换为给定class类型

Class  getType(String name) 返回给定名称的bean的Class,如果没有找到指定的bean实例,则排除NoSuchBeanDefinitionException异常

boolean  isSingleton(String) 判断给定名称的bean定义是否为单例模式      

String[]  getAliases(String name) 返回给定bean名称的所有别名

ApplicationContext接口

​ 是基于BeanFactory之上的,提供了应用程序框架服务,扩展的新功能如下:提供国际化的支持资源访问,如URL和文件 事件传递载入多个配置文件等 实现类常见有三个

ClassPathXmlApplicationContext:-classpath路径加载xml文件的

FileSystemXmlApplicationContext:基于项目根路径进行加载xml文件的

AnnotationConfigApplicationContext:基于注解的配置。基于类书写的配置。

package com.aaa.qy127.controller;

import com.aaa.qy127.service.SpringService;
import com.aaa.qy127.service.impl.SpringServiceImpl;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;

/**
 * @ClassName SpringTest
 * @Description ToDo
 * @Auther teacher Bai
 * @Date 2020/12/19 10:31
 */
public class SpringTest {

    public static void main(String[] args) {
        //这是使用自己new 对象的方式创建对象
        //SpringService service = new SpringServiceImpl();

        /*
        使用读取bean.xml的方式 创建对象
            首先需要读取bean.xml文件
            怎么读?
                1.使用BeanFactory(spring核心容器的顶层接口)
                2.使用BeanFactory的子接口 ApplicationContext(自接口功能更加强大) 常用!
         */
        /**
         * 1.使用BeanFactory(spring核心容器的顶层接口)
         *      ① 读取bean.xml配置文件
         *          ClassPathResource resource = new ClassPathResource("bean.xml");
         *      ② 读取第①步中bean.xml文件中的信息
         *          XmlBeanFactory factory = new XmlBeanFactory(resource);
         *      ③ 通过获取到的factory取出bean对象
         *          Object service1 = factory.getBean("service1");
         */
        ClassPathResource resource = new ClassPathResource("bean.xml");
        XmlBeanFactory factory = new XmlBeanFactory(resource);
        Object service1 = factory.getBean("service1");
        SpringService service = (SpringServiceImpl) service1;
        service.print1();
        /**
         * 2.使用BeanFactory的子接口 ApplicationContext(自接口功能更加强大) 常用!
         *         ① 读取bean.xml配置文件
         *              使用ClassPathXmlApplicationContext实现类   (类路径下的bean.xml)
         *              ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
         *              使用FileSystemXmlApplicationContext实现类 读取文件  (文件系统路径下的bean.xml)
         *              ApplicationContext context = new FileSystemXmlApplicationContext("E:\\课堂笔记\\QY127\\spring\\Spring01-IOC和DI\\spring-02\\src\\bean.xml");
         *         ② 通过获取到的context取出bean对象
         *              SpringService service1 = (SpringServiceImpl)context.getBean("service1");
         *
         */
        //ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        ApplicationContext context = new FileSystemXmlApplicationContext("E:\\课堂笔记\\QY127\\spring\\Spring01-IOC和DI\\spring-02\\src\\bean.xml");
        SpringService service1 = (SpringServiceImpl)context.getBean("service1");
        service1.print1();
    }
}
面试题:BeanFactory 和 ApplicationContext 的区别:
BeanFactory 才是 Spring 容器中的顶层接口。
ApplicationContext 是它的子接口。
单例模式下创建对象的时间点不一样:
ApplicationContext:(饿汉模式)只要一读取配置文件,马上就会创建配置文件中配置的对象。
BeanFactory:(懒加载/懒汉模式)什么时候getBean("id"),也就是说当根据id获取对象时,才会创建。
2.1.1 Spring中的测试函数使用
    @Test
    public void test01(){
        ApplicationContext context  = new ClassPathXmlApplicationContext("Spring.xml");
        People bean = context.getBean(People.class);
        System.out.println(bean);
    }
    我们使用 Junit测试 每次都需要创建 ApplicationContext  对象 非常麻烦,所以使用Spring的测试 性能更好 而且方便。
    
A  导入测试包
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.Springframework</groupId>
      <artifactId>Spring-test</artifactId>
      <version>5.3.7</version>
    </dependency>
B 在测试类中 添加注解
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:Spring.xml")
public class JavaTest {
    @Autowired
    private  ApplicationContext  context;
    @Autowired
    private People  p1;
    @Test
    public void  test(){
        People bean = context.getBean(People.class);
        System.out.println(bean);
    }
    @Test
    public void test01(){
        System.out.println(p1);
    }
}
2.2 getBean()的三种方式

A 通过bean.xml文件中bean标签的id的值获取bean(使用默认构造方法)

Object p1 = context.getBean("唯一标识id");//此处获取的是一个Object类型,可以转换成我们需要的类型。

B 通过类型去获取

People bean = context.getBean(类名.class);

确保bean的类型是唯一的 不然会报错:org.springframework.beans.factory.NoUniqueBeanDefinitionException

C 通过 id + 类型去获取

People bean = context.getBean("p1",People.class);
2.3 创建Bean对象的方式

bean的属性配置

id : 当前bean的唯一标识符

class:配置类的全限定名/全路径

name:配置当前bean的名字,并且可以配置多个。

  • 第一种方式:使用默认构造创建(常用)直接去调用 bean对象中的无参空构造方法来创建对象

    ​ 在spring的bean.xml文件中配置过bean标签,并且设置id和class属性后,会自动的调用默认构造创建对象,如果没有默认的空构造,则对象无法创建。

    <bean id="唯一标识id" class="类的全限定名"></bean>
    
  • 第二种方式:使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器)

    ServiceFactory factory = new ServiceFactory();
    <bean id="普通工厂类的唯一标识" class="工厂类的全限定名"></bean>
    factory.getService();
    <bean id="需要通过工厂创建的对象" factory-bean="上边bean的id" factory-method="工厂中的方法名"></bean>	
    
  • 第三种方式:使用普通工厂的静态方法创建对象

    <!--使用静态工厂的方式创建bean对象-->
    <bean id="accountService" class="工厂类的全类名" factory-method="生产对象的静态方法"></bean>
    
2.4 bean对象的作用范围

bean对象的作用范围调整需要配置scope属性,设置单例还是多例(只针对ApplicationContext接口来说,默认是单例的

scope:常用 singleton,prototype

​ singleton:单例的(默认值)当加载配置文件时,就会创建对象。

​ prototype:多例的(当getBean时才会创建对象)

​ request:作用于请求范围

​ session:作用于会话范围

​ global-session: 全局,作用于分布式集群环境。如果不是集群环境,就是session

image-20201221095109958
<bean id="唯一标识" class="全类名" scope="singleton/prototype"></bean>
默认为singleton单例的:整个程序运行期间对象只会被创建一次。
prototype 多例的,在程序运行期将,用了几次就创建几次对象。
多例对象java的GC垃圾回收机制,在检测到对象长时间不用时,会自动回收/销毁。
2.5 bean对象的生命周期

有的类 对象被创建的时候需要调用初始化函数,对象被回收的时候需要调用销毁函数。现在对象时由spring核心容器去管理的。所以这些函数的调用应该由spring负责。我们只需要通过配置告诉spring初始化函数是谁,销毁函数是谁。bean的生命周期函数。可以同过配置两个方法测试。

init-method:对象的初始化方法

destroy-method:销毁对象的方法(main方法测试时,不会调用销毁方法,是因为还没来得及,速度太快,可以手动销毁,调用close();方法,但是此时ApplicationContext对象应该是子类类型,不能再是ApplicationContext类型了);

  • 单例对象:

    出生:当容器创建时,对象出生

    活着:只要容器还在,对象一直存在

    死亡:容器销毁,对象也销毁

    image-20210113171909778

在这里插入图片描述

初始化方法会被调用,但是销毁方法如果是使用ApplicationContext接口类型,销毁方法无法被调用,需要使用子接口类型,才可以看到销毁方法被调用。context.close();

在这里插入图片描述

  • 多例对象

    出生:当使用对象时,才会创建

    活着:只要使用,一直活着

    死亡:java垃圾回收机制,当对象长时间不用时,GC垃圾回收机制,自动回收。

作业:

​ 1. 复习 servlet所有知识点

​ 2. 掌握今天讲解的知识点

​ 3. 预习 依赖注入和springMVC

​ 4. 增删改查不行的,接着搞!

第四节:依赖注入DI

相当于你请对象去吃饭、买衣服、送礼物啊

IOC:控制反转 创建对象!

依赖注入:目的就是给对象中的属性赋值。

对象中的属性都可以是哪些数据类型:基本类型,String , Date, List<?>----->基本,引用

1.简介

依赖注入(Dependency Injection)

IOC控制反转的最终目的就是降低程序的耦合,也就是削减依赖关系。

依赖关系的管理以后都交给spring维护,依赖关系的管理就称之为依赖注入。也就是说在当前类需要用到其它类的对象时,由spring为我们提供,我们只需要在配置文件中说明依赖关系的维护就可以了。

依赖注入的方式

依赖注入的数据:三种类型

​ 1. 基本数据类型和String

2. 其它bean实体对象类型(在配置文件中或者注解配置过的bean)
3. 复杂类型/集合类型(集合类型只能通过配置文件注入)

什么时候使用IOC和DI创建对象?

​ 如果是单例对象,可以使用IOC和DI。整个程序运行期间只会创建一个对象,我们不用考虑对象中数据的改变。

​ 但是,如果我们要创建的对象中的属性值,一直在改变,此时就不推荐使用DI和IOC了。

2.第一种:使用构造函数提供注入

​ argument

​ 如果使用构造函数注入,需要在bean.xml文件的bean标签中添加constructor-arg标签

​ 标签中的属性:

​ type : 用于指定要注入的数据的类型,该数据类型也是构造函数中某个或某些参数的类型。

​ index: 用指定给构造函数中指定索引位置的参数赋值,索引从0开始。

​ name: 用于给构造函数的参数赋值,指定参数的名称直接赋值 (常用)

​ value : 用于提供基本类型和String类型的数据

​ ref : 用于指定其它的bean类型数据,它指的就是在spring的IOC核心容器中出现过的bean

注意:在获取bean对象时,必须要注入数据,否则对象无法创建成功。

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

 <!--构造注入-->
    <bean id="p1" class="com.bai.demo2.entity.Person">
        <constructor-arg name="age" value="18"></constructor-arg>
        <constructor-arg name="name" value="张三"></constructor-arg>
        <constructor-arg name="date" ref="d1"></constructor-arg>
    </bean>

    <!--日期对象的bean-->
    <bean id="d1" class="java.util.Date"></bean>
3.第二种:使用set方法注入(常用)

​ 如果使用set函数注入,需要在bean.xml文件的bean标签中添加 property 标签

​ 需要属性:

​ name: 用于给无参空构造函数的参数赋值,指定设值的set方法(将set方法的set去掉把大写字母变小写 setAge()====>age)

​ value : 用于提供基本类型和String类型的数据

​ ref : 用于指定其它的bean类型数据,它指的就是在spring的IOC核心容器中出现过的bean

​ **优点:**解决了构造注入时的问题,可以选择性的注入值,不是必须注入全部了。

 	<!--注入java提供的Date类-->
    <bean id="date" class="java.util.Date"></bean>
    <!--set方法注入-->
    <bean id="person" class="com.aaa.ioc.Person">
        <property name="name" value="李四"></property>
        <property name="age" value="29"></property>
        <property name="birthday" ref="date"></property>
    </bean>
3.复杂数据类型的注入

数组、集合(LIst、Set、Map、Properties)

<!--    配置bean,放在spring的IOC容器-->
    <bean id="depart" class="com.aaa.entity.Depart">
        <property name="id" value="1"/>
        <property name="name" value="腾讯战略投研部"/>
        <!-- 集合的注入;array  n个子标签value -->
        <property name="emps">
            <array>
                <value>马化腾</value>
                <value>刘治平</value>
                <value>江二涛</value>
                <value>苏磊</value>
            </array>
        </property>
        <property name="nicknames">
            <list>
                <value>小马哥</value>
                <value>投资帝</value>
                <value>江郎</value>
                <value>苏仙</value>
            </list>
        </property>
        <property name="hobbies">
            <set>
                <value>王者</value>
                <value>游戏</value>
                <value>产品</value>
                <value>产品</value>
            </set>
        </property>
        <!-- 如何遍历?先写map  Entry  -->
        <property name="maps">
            <map>
                <entry>
                    <key>
                        <value>football</value>
                    </key>
                    <value>足球</value>
                </entry>
                <entry key="bassketball" value="篮球"></entry>
                <entry key="pingpangball" value="乒乓球"/>
            </map>
        </property>
        <!-- props:复数;一般用在配置文件,是Map的简化版本;-->
        <property name="properties">
            <props>
                <prop key="dirver">com.mysql.cj.jdbc.Driver</prop>
                <prop key="url">http:///school:3306</prop>
                <prop key="username">root</prop>
                <prop key="password">root</prop>
            </props>
        </property>
    </bean>

针对Properties类的操作

//如果和来获取相应的集合数据,depart获取完毕后;简化版的HashMap
        Properties properties = depart.getProperties();
        String driver = properties.getProperty("driver");
        String url = properties.getProperty("url");
        String username = properties.getProperty("username");
        String password = properties.getProperty("password");
        System.out.println(driver+"\t"+url+"\t"+username+"\t"+password);

5.SpEL,EL表达式,在web页面,对变量输出;

 <!--spel:格式;#{bean的id名.属性名}-->
     <bean id="emp" class="com.aaa.entity.Emp">
         <property name="eid" value="2"/>
         <property name="ename" value="乔玉奇"/>
         <property name="dname" value="#{depart.name}"/>
     </bean>
6.注入外部文件

${key}这样的表达式在XML中,代表引入的properties文件中key对应的一个变量值,完全是靠第三方jar自己解析的,xml格式读取的符号。


为了解决很多无效的配置文件,可以使用注解。

4.第三种:使用注解提供 (注意开启注解的包扫描)
<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="要扫描的包全名"></context:component-scan>
</beans>

注解分类

1.用于创建对象的:

​ 作用和在xml配置文件中编写一个< bean>标签实现的功能一样

@Component:(只要不属于三层架构 就使用)
	作用:用于把当前类对象存入spring容器中。
	具有value属性,用于指定bean的id,如果不写value,默认跟当前类名对应(首字母改小写)
	@Component("student1")作用就相当于:
	<bean id="student1" class="全类名"></bean>	
衍生三个注解:
@Controller(表现层)     @Service(业务层)      @Repository(持久层)
	这三个注解的作用和@Component注解一样,是spring框架为我们提供的明确的三层架构使用的注解,让我们的三层架构更加清晰。

2.用于注入数据的

​ 作用和xml文件中bean标签中的property标签的作用一样
在这里插入图片描述

@Autowired 重点
作用:自动按照类型注入,只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。
    如果IOC容器中没有任何bean的类型和要注入的变量类型匹配,则报错
    如果IOC容器中有多个类型匹配时,会根据要注入的变量名作为id去匹配,如果匹配到了,就可以执行,否则,报错。
注意:使用注解时,set方法就不是必要的了。
以上@Autowired注解存在一定的局限性,(如果核心容器中有多个相同对象,只使用@Autowired是无法注入成功的)如何解决问题?
@Qualifier
	作用:在按照类型注入的基础上再按照名称注入。它再给类成员注入时不能单独使用。但是再给方法注入时可以。
	属性:value 用于指定注入的bean的id
@Resource
	作用:直接按照bean的id注入。它可以独立使用。
	属性:name   用于指定bean的id
以上三个注解都只能注入其它bean类型的数据,而基本类型和String类型无法使用上述注解。那么如何注入基本数据类型和String类型呢?(集合类型只能通过xml注入)
@Value
	作用:用于注入基本数据类型和String数据类型。

在这里插入图片描述

3.用于改变作用范围的

​ 作用和bean标签中的scope属性的功能一样

@Scope:
	作用:用于指定bean的作用范围
	属性:value  指定范围的取值。常用  singleton  prototype

4.和生命周期相关的

​ 作用和bean标签中的init-method和destory-method方法的作用一样

@PostConstruct:用于指定初始化方法
@PreDestroy	  :用于指定销毁方法
5.测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring_ano_bean.xml")

总结:

BeanFactory接口和ApplicationContext接口的区别:

getBean() 方法

依赖注入:

​ 构造注入

​ set注入

​ 注解注入

作业:

改造三层架构

模拟三层架构

service,impl

dao,impl

controller(测试类)

理清楚依赖关系。

rce
作用:直接按照bean的id注入。它可以独立使用。
属性:name 用于指定bean的id
以上三个注解都只能注入其它bean类型的数据,而基本类型和String类型无法使用上述注解。那么如何注入基本数据类型和String类型呢?(集合类型只能通过xml注入)
@Value
作用:用于注入基本数据类型和String数据类型。


[外链图片转存中...(img-SEsBVE0f-1645885880932)]

**3.用于改变作用范围的**:

​		作用和bean标签中的scope属性的功能一样

```properties
@Scope:
	作用:用于指定bean的作用范围
	属性:value  指定范围的取值。常用  singleton  prototype

4.和生命周期相关的

​ 作用和bean标签中的init-method和destory-method方法的作用一样

@PostConstruct:用于指定初始化方法
@PreDestroy	  :用于指定销毁方法
5.测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring_ano_bean.xml")

总结:

BeanFactory接口和ApplicationContext接口的区别:

getBean() 方法

依赖注入:

​ 构造注入

​ set注入

​ 注解注入

作业:

改造三层架构

模拟三层架构

service,impl

dao,impl

controller(测试类)

理清楚依赖关系。

分别使用bean.xml方式配置,和注解方式配置。完成三层架构的调用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

teayear

读后有收获可以支付宝请作者喝咖

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值