Spring IoC容器(一)

news2024/11/19 15:15:27

 IoC,Inversion of Control 控制反转,是一个过程。仅通过构造函数、工厂方法或在对象实例化后在对象实例上设置属性来定义其依赖关系。容器负责这些工作,这个过程从本质上来说是bean本身的反向,因此称为反向控制。

1 容器

负责实例化、配置及装配bean。容器从配置元数据那获取该怎么实例化、配置及装配bean。而配置来源主要有三个:1)XML;2)java注释;3)java代码。xml比较常用。

@Configuration // 将一个普通类标志为IoC容器
public class CustomConfig {
    @Bean // 定义一个bean
    public User customUser() {
        return new User();
    }
}

private static void test1() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CustomConfig.class);
    User user = context.getBean(User.class);
    System.out.println(user);
}

上面代码展示了java代码配置bean的方式。通过AnnotationConfigApplicationContext来获取容器。

图 ApplicationContext的方法及实现类

BeanFactory 接口提供了管理Bean的方法,而ApplicationContext继承了该接口,并有以下扩展:

1)更容易与Spring 的aop集成。

2)消息资源处理。

3)事件发布。

4)针对web项目,提供了特定的子类。

图 ApplicationContext的方法及实现类

2 Bean

构成程序主干并由IoC容器管理的对象称为bean。

在模块化开发中,不同模块的容器可能存在依赖了同一bean的bean。有时,我们考虑到扩展或者在某个模块中有特定的命名规范,所依赖的这个bean的命名可能会不同。 比如模块A、B依赖同一个数据源配置bean。 在模块A中该bean命名为datasourceA,在模块B中命名为datasourceB。这时候需要用到别名。

<!--数据源,common.xml-->
<bean id="datasource" class="dao.BaseDao"/>

<!--模块A a.xml-->
<import resource="dao.xml"/>

<!—别名-->
<alias name="datasource" alias="datasourceA"/>
<bean id="teacherService" class="service.TeacherService">
    <property name="baseDao" ref="baseDao"/>
</bean>

2.1 实例化

xml配置中,实例化bean有三种方式:1)构造函数;2)静态工厂方法;3)bean的工厂方法。

public class GoodsDao {
}

public class GoodsService {
    public GoodsDao makeGoodsDao() {
        return new GoodsDao();
    }
}

public class StaticFactory {
    public static GoodsService makeGoodsService() {
        return new GoodsService();
    }
}

<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
        https://www.springframework.org/schema/beans/spring-beans.xsd" default-lazy-init="true">
    <!--构造函数实例化-->
    <bean id="goodsService" class="instantiating.GoodsService"/>

    <!--静态工厂实例化,class为该工厂的类-->
    <bean id="goodsService2" class="instantiating.StaticFactory" factory-method="makeGoodsService"/>

    <!--bean的工厂实例化-->
    <bean id="goodsDao" factory-bean="goodsService" factory-method="makeGoodsDao"/>
</beans>

3 依赖

依赖是指对象在运行中需要用到的其他对象。在IoC中由容器负责注入。注入方式有两种:1)构造函数;2)set方法。

public class OtherDao {
}

public class ReportDao {
}

public class ReportService {

    private ReportDao reportDao;
    private String name;
    private Double num;

    public ReportService(ReportDao reportDao, String name, Double num) {
        this.reportDao = reportDao;
        this.name = name;
        this.num = num;
    }

    private Properties dataProperties;
    private Map<String, String> stockInfoMap;
    private List<String> links;

    private OtherDao otherDao;

    public void setDataProperties(Properties dataProperties) {
        this.dataProperties = dataProperties;
    }

    public void setStockInfoMap(Map<String, String> stockInfoMap) {
        this.stockInfoMap = stockInfoMap;
    }

    public void setLinks(List<String> links) {
        this.links = links;
    }

    public void setOtherDao(OtherDao otherDao) {
        this.otherDao = otherDao;
    }

    @Override
    public String toString() {
        return "ReportService{" +
                "reportDao=" + reportDao +
                ", name='" + name + '\'' +
                ", num=" + num +
                ", dataProperties=" + dataProperties +
                ", stockInfoMap=" + stockInfoMap +
                ", links=" + links +
                ", otherDao=" + otherDao +
                '}';
    }

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("dependency.xml");
        ReportService reportService = applicationContext.getBean(ReportService.class);
        System.out.println(reportService);
    }
}

<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
        https://www.springframework.org/schema/beans/spring-beans.xsd" default-lazy-init="true">
    <bean id="reportDao" class="dependency.ReportDao"/>

    <bean id="reportService" class="dependency.ReportService">
<!--        constructor-arg 为构造函数参数,参数可以依赖其他bean,也可以是基本类似-->
        <constructor-arg name="reportDao" ref="reportDao"/>
        <constructor-arg name="name" value="reportService层"/>
        <constructor-arg name="num" value="103.4"/>
<!--        set方法,来注入参数-->
<!--        Properties类型-->
        <property name="dataProperties">
            <props>
                <prop key="host">localhost</prop>
                <prop key="username">admin</prop>
                <prop key="password">123</prop>
            </props>
        </property>
<!--        Map类型-->
        <property name="stockInfoMap">
            <map>
                <entry key="name" value="中国平安"/>
                <entry key="stock" value="601318.sh"/>
            </map>
        </property>
<!--        List类型-->
        <property name="links">
<!--            空值-->
            <null />
        </property>
        <property name="otherDao">
<!--            内部bean,可以不要id或者name,不会被其他bean依赖-->
            <bean class="dependency.OtherDao"/>
        </property>
    </bean>
</beans>

3.1 depends-on与懒加载

容器创建一个bean时,会先创建起依赖的bean。但是有时两个bean直接没有直接依赖,但是希望在创建这个bean之前,先创建其他的bean。可用depends-on来完成这个需求:

<bean id="teacherDao" class="dao.TeacherDao" depends-on="userDao,baseDao"/>

在创建teacherDao这个bean之前,会先创建userDao及baseDao这两个bean。

在容器中,默认会在项目加载时把所有的bean都创建完成,这样做的好处是某个bean的配置错误能在运行时被发现。但是有时不希望创建所有的bean,希望当要使用这个bean时再来创建,default-lazy-init  懒加载属性可以作用于全局的beans,也可以作用于单个的beans。当值为true时,bean在第一次使用时才会被创建。

3.2 方法注入

假如bean1的某个方法,在每次调用时都需要一个特定的bean2(不是bean1的直接依赖,即非bean1的字段)。传统方法是,可以在该方法中通过ApplicationContext获取bean2。这是这样加大了耦合度,容器提供了Lookup标签来实现此类需求:

public class Bean2 {
}

public class Bean1 {

    private final static ApplicationContext applicationContext = new ClassPathXmlApplicationContext("method.xml");

    /**
     * 传统方式
     */
    public void showBean2OfTradition() {
        Object bean2 = applicationContext.getBean("bean2");
        System.out.println(bean2);
    }

    /**
     * Lookup 方法
     */
    public Bean2 getBean2() {
        return null;
    }

    public static void main(String[] args) {
        Bean1 bean1 = applicationContext.getBean(Bean1.class);
        bean1.showBean2OfTradition();
        System.out.println(bean1.getBean2());
    }
}

<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
        https://www.springframework.org/schema/beans/spring-beans.xsd" default-lazy-init="true">
    <bean id="bean1" class="method.Bean1">
<!--        会覆盖原getBean2方法,直接返回bean2-->
        <lookup-method name="getBean2" bean="bean2"/>
    </bean>
    <bean id="bean2" class="method.Bean2"/>
</beans>

4 作用域

bean 也可以指定作用域(生命周期),Spring支持六种作用域。bean的scope属性来指定该bean的作用域。

singleton

默认作用域。不同容器生成的bean不同。

prototype

在同一容器中,不同bean依赖的bean被创建的实例不同。

request

每次请求都会创建不同的bean。

session

每个session都会创建不同 bean。

application

每个servletContext生成不同的bean。

websocket

每个websocket连接生成不同的bean。

表 spring 的六种bean的作用域

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

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

相关文章

Linux系列之查看cpu、内存、磁盘使用情况

查看磁盘空间 df命令用于显示磁盘分区上的可使用的磁盘空间。默认显示单位为KB。可以利用该命令来获取硬盘被占用了多少空间&#xff0c;目前还剩下多少空间等信息。使用df -h命令&#xff0c;加个-h参数是为了显示GB MB KB单位&#xff0c;这样更容易查看 Filesystem …

2024年软考高项备考攻略

一、了解考试大纲和要求 在开始备考之前&#xff0c;首先要对考试大纲和要求进行全面了解。这有助于明确考试内容和学习方向&#xff0c;制定学习计划。 二、制定学习计划 在制定计划时&#xff0c;可以根据自己的实际情况和学习习惯&#xff0c;选择适合自己的学习方式。以…

LocalContainerEntityManagerFactoryBean源码

是 Spring Data JPA 中的一个类&#xff0c;它用于创建 EntityManagerFactory 的实例&#xff0c;获取EntityManager实例 public class LocalContainerEntityManagerFactoryBean extends AbstractEntityManagerFactoryBeanimplements ResourceLoaderAware, LoadTimeWeaverAwar…

Netty源码二:服务端创建NioEventLoopGroup

示例 还是拿之前启动源码的示例&#xff0c;来分析NioEventLoopGroup源码 NioEventLoopGroup构造函数 这里能看到会调到父类的MultiThread EventLoopGroup的构造方法 MultiThreadEventLoopGroup 这里我们能看到&#xff0c;如果传入的线程数目为0&#xff0c;那么就会设置2倍…

RabbitMQ-如何保证消息不丢失

RabbitMQ常用于 异步发送&#xff0c;mysql&#xff0c;redis&#xff0c;es之间的数据同步 &#xff0c;分布式事务&#xff0c;削峰填谷等..... 在微服务中&#xff0c;rabbitmq是我们经常用到的消息中间件。它能够异步的在各个业务之中进行消息的接受和发送&#xff0c;那么…

代码随想录算法刷题训练营day19

代码随想录算法刷题训练营day19&#xff1a;LeetCode(404)左叶子之和、LeetCode(112)路径总和、LeetCode(113)路径总和 II、LeetCode(105)从前序与中序遍历序列构造二叉树、LeetCode(106)从中序与后序遍历序列构造二叉树 LeetCode(404)左叶子之和 题目 代码 /*** Definitio…

GitHub 上传文件夹到远程仓库、再次上传修改文件、如何使用lfs上传大文件、github报错一些问题

按照大家的做法&#xff0c;把自己遇到的问题及解决方案写出来&#xff08;注意&#xff1a;Error里面有些方法有时候我用可以成功&#xff0c;有时候我用也不能成功&#xff0c;写出来仅供参考&#xff0c;实在不行重头再clone&#xff0c;add&#xff0c;commit&#xff0c;p…

Virtual Assistant for Smartphone;Denoising Autoencoder;CrossMAE

本文首发于公众号&#xff1a;机器感知 Virtual Assistant for Smartphone&#xff1b;Denoising Autoencoder&#xff1b;CrossMAE The Case for Co-Designing Model Architectures with Hardware While GPUs are responsible for training the vast majority of state-of-t…

dvwa,xss反射型lowmedium

xss&#xff0c;反射型&#xff0c;low&&medium low发现xss本地搭建实操 medium作为初学者的我第一次接触比较浅的绕过思路 low 发现xss 本关无过滤 <script>alert(/xss/)</script> //或 <script>confirm(/xss/)</script> //或 <script&…

vulnhub靶场之EMPIRE:BREAKOUT

一.环境搭建 1.靶场描述 Description Back to the Top Difficulty: Easy This box was created to be an Easy box, but it can be Medium if you get lost. For hints discord Server ( https://discord.gg/7asvAhCEhe ) 2.靶场地址 https://www.vulnhub.com/entry/empire-…

Canny边缘检测算法(python 实现)

1. 应用高斯滤波来平滑(模糊)图像&#xff0c;目的是去除噪声 2. 计算梯度强度和方向&#xff0c;寻找边缘&#xff0c;即灰度强度变化最强的位置 3应用非最大抑制技术NMS来消除边误检模糊&#xff08;blurred&#xff09;的边界变得清晰&#xff08;sharp&#xff09;。保留了…

力扣题目训练(3)

2024年1月27日力扣题目训练 2024年1月27日力扣题目训练290. 单词规律292. Nim 游戏303. 区域和检索 - 数组不可变91. 解码方法92. 反转链表 II41. 缺失的第一个正数 2024年1月27日力扣题目训练 2024年1月27日第三天编程训练&#xff0c;今天主要是进行一些题训练&#xff0c;包…

机器学习算法实战案例:使用 Transformer 模型进行时间序列预测实战(升级版)

时间序列预测是一个经久不衰的主题&#xff0c;受自然语言处理领域的成功启发&#xff0c;transformer模型也在时间序列预测有了很大的发展。 本文可以作为学习使用Transformer 模型的时间序列预测的一个起点。 文章目录 机器学习算法实战案例系列答疑&技术交流数据集数据…

Java RC4加密算法

一、RC4加密算法 在密码学中&#xff0c;RC4&#xff08;来自Rivest Cipher 4的缩写&#xff09;是一种流加密算法&#xff0c;密钥长度可变。它加解密使用相同的密钥&#xff0c;因此也属于对称加密算法。 百度百科 - RC4&#xff1a;https://baike.baidu.com/item/RC4/34545…

揭秘1688商品详情API接口:一探阿里巴巴的亿级商品数据宝藏

一、概述 1688商品详情API接口是阿里巴巴提供的一套应用程序接口&#xff0c;允许第三方开发者获取1688平台上的商品详情信息。通过使用这个接口&#xff0c;开发者可以获取到商品的详细属性、规格参数、价格等信息&#xff0c;从而进行深度分析和挖掘&#xff0c;进一步优化和…

selenium元素定位---元素点击交互异常解决方法

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;薪资嘎嘎涨 1、异常原因 在编写ui自动化时&#xff0c;执行报错元素无法点击&#xff1a;ElementClickIn…

基础算法之Huffman编码

// Type your code here, or load an example. #include<iostream> #include<string> #include<queue> #include <unordered_map> #include <vector>using namespace std;//树节点结构 struct Node {char ch;int freq;Node *left;Node *right;No…

【数据结构】(一)从绪论到各种线性表

目录 一、绪论Introduction 1、数据结构 2、逻辑结构&#xff08;数据元素之间的相互关系&#xff09; 3、物理结构&#xff08;数据逻辑结构在计算机中的存储形式&#xff09; 4、数据类型&#xff08;一组性质相同的值的集合及定义在此集合上的一些操作的总称&#xff09…

幻兽帕鲁服务器多少钱?2024年Palworld游戏主机费用

幻兽帕鲁服务器多少钱&#xff1f;价格便宜&#xff0c;阿里云4核16G幻兽帕鲁专属服务器32元1个月、66元3个月&#xff0c;4核32G配置113元1个月、339元3个月&#xff1b;腾讯云4核16G14M服务器66元1个月、277元3个月、1584元一年。阿腾云atengyun.com分享阿里云和腾讯云palwor…

Python算法题集_找到字符串中所有字母异位词

本文为Python算法题集之一的代码示例 题目438&#xff1a;找到字符串中所有字母异位词 说明&#xff1a;给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字…