草庐IT

Spring——IOC底层原理

星星下雪 2023-08-02 原文

目录

一、IOC底层原理

1.什么是IOC

2.IOC底层原理

二、IOC接口(BeanFanctory)

三、IOC操作Bean管理(基于XML)

1.创建对象

2.注入属性

(1)DI:依赖注入

(2)p名称空间注入(了解)

(3)注入其他类型属性

(4)注入外部bean 

(5)注入内部bean和级联赋值

(6)注入集合类型

 4.属性注入细节


一、IOC底层原理

1.什么是IOC

        通过控制反转(Inversion of Control,缩写为IOC),对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

        1)控制反转,把对象的创建和对象之间调用的过程,交给Spring进行管理

        2)使用IOC目的:降低耦合度

        3)入门案例即为IOC的实现(入门案例:【网址】)

2.IOC底层原理

(1)XML解析 + 工厂设计模式 + 反射(令耦合度尽可能的降低到最小)

通过画图来讲解IOC底层原理:

二、IOC接口(BeanFanctory)

  1. IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
  2. Spring提供IOC容器实现的两种方式(两个接口,两个接口均可加载XML文件并且获取配置创建的对象):

        (1)BeanFactory:IOC容器基本实现方式,是Spring内部使用的接口,不提供开发人员使用。

                特点:加载配置文件时不会创建对象,而是在获取对象或者使用对象时才去创建对象。

        (2)ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般面向开发人员使用。

                特点:加载配置文件时,直接创建对象。

 ApplicationContext中有两个主要的实现类:

1. FileSystemXmlApplicationContext:括号中时配置文件的全路径。

2. ClassPathXmlApplicationContext:括号中直接配置文件名。

三、IOC操作Bean管理(基于XML)

Bean管理(两个操作):

        (1)Spring创建对象

        (2)Spring属性注入

1.创建对象

                

                a. 在Spring配置文件中,使用bean标签,标签里面添加对应的属性,就可以实现对象创建。

                b. 在bean标签中有很多属性,常见的有:

                * id 属性:设置类的唯一标识(并不是直接指对象名称);

                * Class属性 :类全路径(包类路径);

                c. 创建对象的时候,默认执行无参构造器方法(若使用有参构造器,且未构成无参构造器,此时无参构造器被覆盖,所以常规获取对象方式报错)

2.注入属性

(1)DI:依赖注入

是AOC的一种具体实现,必须在创建对象的基础之上完成。

 * 第一种注入方式:set方法注入

i.

/**
 * 演示使用set方法进行属性注入
 */
public class Book {
    //创建属性
    private String bname;
    private String bauthor;

    //创建属性对应的set方式注入

    public void setBname(String bname) {
        this.bname = bname;
    }

    public void setBauthor(String bauthor) {
        this.bauthor = bauthor;
    }
    
    public void TestBook(){
        System.out.println(bname + " :: "+bauthor);
    }
}

 ii.在Spring配置文件中配置对象创建,配置属性注入

<bean id="Book" class="com.xx.Spring.Book">
    <!--使用property完成属性注入
        name:类里面的属性名称
        value:向属性注入的值
    -->
    <property name="bname" value="数据结构"></property>
    <property name="bauthor" value="xxx"></property>
</bean>

iii. 测试代码 

public void TestBook(){
    ApplicationContext context =
            new ClassPathXmlApplicationContext("bean1.xml");
    Book book = context.getBean("Book", Book.class);
    book.TestBook();
}

输出结果:

第二种注入方式:使用有参构造器注入

package com.xx.Spring.testDome;

/**
 * 演示使用有参构造来进行属性注入
 */
public class Orders {
    private String oname;
    private String address;

    public Orders(String oname, String address) {
        this.oname = oname;
        this.address = address;
    }
    public void Test(){
        System.out.println(oname + ":" + address);
    }
}
<bean id="Oders" class="com.xx.Spring.testDome.Orders">
    <constructor-arg name="oname" value="abc"></constructor-arg>
    <constructor-arg name="address" value="123"></constructor-arg>
</bean>
@Test
public void TestOrder(){
    ApplicationContext context =
            new ClassPathXmlApplicationContext("bean1.xml");
    Orders oders = context.getBean("Oders", Orders.class);
    oders.Test();
}

(2)p名称空间注入(了解)

        a. 使用p名称空间注入,可以简化基于xml配置方式

第一步:添加 p 名称空间在配置文件中

第二步:进行属性注入,在bean标签中进行操作

<bean id="Book" class="com.xx.Spring.Book" p:bname="高频电子线路" p:bauthor="周珩">
    
</bean>

测试:

@Test
public void TestBook() {
    ApplicationContext context =
            new ClassPathXmlApplicationContext("bean1.xml");
    Book book = context.getBean("Book", Book.class);
    book.TestBook();
}

 结果:

(3)注入其他类型属性

1.字面量

    (1)null

<bean id="Book" class="com.xx.Spring.Book">
    <!--设置一个空值-->
    <property name="bname" value="数据结构"></property>
    <property name="bauthor">
        <null/>
    </property>
</bean>

    (2)特殊符号

<bean id="Book" class="com.xx.Spring.Book">
    <!--属性值包含特殊符号
        1.把<>进行转义 &lt;&gt;
        <property name="bauthor" value="&lt;&gt;<<南京>>"></property>
        2.把带特殊符号的内容写道CDATA
    -->
    <property name="bauthor" >
        <value><![CDATA[<<南京>>]]></value>
    </property>
</bean>

(4)注入外部bean 

a.创建Service类和Dao类

b.在Service类中调用Dao类中的方法

c.在Spring配置文件中进行配置

//测试
@Test
public void TestBean1(){
    ApplicationContext context =
            new ClassPathXmlApplicationContext("Bean1.xml");
    UserService userService = context.getBean("userService", UserService.class);
    userService.add();
}

/*结果:
Service.add运行.....
Dao.updata运行....
*/

(5)注入内部bean和级联赋值

 a.一对多关系:部门和员工(一个部门有多个员工,一个员工属于一个部门);

b.在实体类之间标识一对多(员工表示所属部门),使用对象类型属性进行表示;

c.在Spring配置文件中进行配置

public void TestBean_(){
    ApplicationContext context =
            new ClassPathXmlApplicationContext("Bean_.xml");
    Emp emp = context.getBean("emp", Emp.class);
    emp.add();
}

/*结果:
id = 1 ename = xx dept = Dept{dname='研发部'}
*/

注:配置文件也可以使用级联赋值的方式

也可以这样写: 但注意此时的结果: 

已经将bean标签中的value值覆盖!!!

(6)注入集合类型

集合类型(List、Map、Set)

1.注入数组类型属性

2.注入list集合属性

3.注入Map集合类型的属性

(1)创建类,定义数组、list、map、set集合类型属性,并生成对应的set方法

package com.xx.Spring2.collectionType;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Stu {
    //1.数组类型属性
    private String[] course;
    //2.List集合类型属性
    private List<String> list;
    //3.Map集合类型的属性
    private Map<String, String> mapS;
    //4.Set集合类型属性
    private Set<String> sets;

    public void setCourse(String[] course) {
        this.course = course;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setMapS(Map<String, String> mapS) {
        this.mapS = mapS;
    }

    public void setSets(Set<String> sets) {
        this.sets = sets;
    }

    public void test(){
    System.out.println(Arrays.toString(course));
    System.out.println("===============");
    System.out.println(list);
    System.out.println("===============");
    System.out.println(maps);
    System.out.println("===============");
    System.out.println(sets);
    }
}

(2)在Spring配置文件中进行配置

<?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="stu" class="com.xx.Spring2.collectionType.Stu">
    <!--1.数组类型注入-->
    <property name="course" >
        <array>
            <value>英语</value>
            <value>语文</value>
            <value>数学</value>
            <value>历史</value>
        </array>
    </property>
    
    <!--list集合类型注入-->
    <property name="list" >
        <array>
            <value>张三</value>
            <value>三三</value>
        </array>
    </property>

    <!--map集合类型注入-->
    <property name="maps">
        <map>
            <entry key="1" value="数学"></entry>
            <entry key="2" value="语文"></entry>
        </map>
    </property>

    <!--set集合类型注入-->
    <property name="sets">
        <set>
            <value>mysql</value>
            <value>java</value>
        </set>
    </property>
</bean>

</beans>
//测试
package com.xx.Spring2.TestArray;

import com.xx.Spring2.collectionType.Stu;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    @org.junit.Test
    public void TestBeanArray(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beanArray.xml");

        Stu stu = context.getBean("stu", Stu.class);

        stu.test();
    }
}
/*结果:
[英语, 语文, 数学, 历史]
===============
[张三, 三三]
===============
{1=数学, 2=语文}
===============
[mysql, java]
*/

 4.属性注入细节

1.若集合中储存对象类型的值

(比如每个学生可以学多门课程,创建Course类,并且在Stu类中创建list集合来储存多个course对象,再构建其对应的set方法)

package com.xx.Spring2.collectionType;

public class Course {
    private String cname;

    public void setCname(String cname) {
        this.cname = cname;
    }
}

在配置文件中配制时,首先创建多个course对象

<!--创建多个course对象-->
<bean id="course1" class="com.xx.Spring2.collectionType.Course">
    <property name="cname" value="数据结构"></property>
</bean>
<bean id="course2" class="com.xx.Spring2.collectionType.Course">
    <property name="cname" value="Spring5"></property>
</bean>

再使用外部标签注入

<!--list对象类型值注入-->
<property name="courseList">
    <list>
        <ref bean="course1"></ref>
        <ref bean="course2"></ref>
    </list>
</property>

2.不同类中,用到相同的集合类型(目前的配置文件的说明只注入一个类中,解决方法:将list结合的配置提取,做成公共部分,让所有的类均能引入该集合)

(1)在Spring配置中先引入一个名称空间 (util)

(2)使用Util标签完成list集合注入提取

【关于IOC操作Bean管理(基于beanFactory)笔记可转:】

有关Spring——IOC底层原理的更多相关文章

  1. ruby-on-rails - 带 Spring 锁的 Rails 4 控制台 - 2

    我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.

  2. spring.profiles.active和spring.profiles.include的使用及区别说明 - 2

    转自:spring.profiles.active和spring.profiles.include的使用及区别说明下文笔者讲述spring.profiles.active和spring.profiles.include的区别简介说明,如下所示我们都知道,在日常开发中,开发|测试|生产环境都拥有不同的配置信息如:jdbc地址、ip、端口等此时为了避免每次都修改全部信息,我们则可以采用以上的属性处理此类异常spring.profiles.active属性例:配置文件,可使用以下方式定义application-${profile}.properties开发环境配置文件:application-dev

  3. ruby-on-rails - Spring 不起作用。 [未初始化常量 Spring::SID::DL] - 2

    我无法运行Spring。这是错误日志。myid-no-MacBook-Pro:myid$spring/Users/myid/.rbenv/versions/1.9.3-p484/lib/ruby/gems/1.9.1/gems/spring-0.0.10/lib/spring/sid.rb:17:in`fiddle_func':uninitializedconstantSpring::SID::DL(NameError)from/Users/myid/.rbenv/versions/1.9.3-p484/lib/ruby/gems/1.9.1/gems/spring-0.0.10/li

  4. 【云原生】SpringCloud-Spring Boot Starter使用测试 - 2

    目录SpringBootStarter是什么?以前传统的做法使用SpringBootStarter之后starter的理念:starter的实现: 创建SpringBootStarter步骤在idea新建一个starter项目、直接执行下一步即可生成项目。 在xml中加入如下配置文件:创建proterties类来保存配置信息创建业务类:创建AutoConfiguration测试如下:SpringBootStarter是什么? SpringBootStarter是在SpringBoot组件中被提出来的一种概念、简化了很多烦琐的配置、通过引入各种SpringBootStarter包可以快速搭建出一

  5. 【Unity游戏破解】外挂原理分析 - 2

    文章目录认识unity打包目录结构游戏逆向流程Unity游戏攻击面可被攻击原因mono的打包建议方案锁血飞天无限金币攻击力翻倍以上统称内存挂透视自瞄压枪瞬移内购破解Unity游戏防御开发时注意数据安全接入第三方反作弊系统外挂检测思路狠人自爆实战查看目录结构用il2cppdumper例子2-森林whoishe后记认识unity打包目录结构dll一般很大,因为里面是所有的游戏功能编译成的二进制码游戏逆向流程开发人员代码被编译打包到GameAssembly.dll中使用il2ppDumper工具,并借助游戏名_Data\il2cpp_data\Metadata\global-metadata.dat

  6. Spring Boot集成ElasticSearach - 2

    文章目录前言一、Elasticsearch版本介绍二、客户端种类三、客户端与版本兼容性四、引入Elasticsearch依赖包五、客户端配置六、Elasticsearch使用前言ElasticSearch是Elastic公司出品的一款功能强大的搜索引擎,被广泛的应用于各大IT公司,它的代码位于https://github.com/elastic/elasticsearch,目前是一个开源项目。ElasticSearch公司的另外两个开源产品Logstash、Kibana与ElasticSearch构成了著名的ELK技术栈。。他们三个共同形成了一个强大的生态圈。简单地说,Logstash负责数据

  7. Spring Security 6.0系列【32】授权服务器篇之默认过滤器 - 2

    有道无术,术尚可求,有术无道,止于术。本系列SpringBoot版本3.0.4本系列SpringSecurity版本6.0.2本系列SpringAuthorizationServer版本1.0.2源码地址:https://gitee.com/pearl-organization/study-spring-security-demo文章目录前言1.OAuth2AuthorizationServerMetadataEndpointFilter2.OAuth2AuthorizationEndpointFilter3.OidcProviderConfigurationEndpointFilter4.N

  8. IDEA 2022 创建 Spring Boot 项目详解 - 2

    如何用IDEA2022创建并初始化一个SpringBoot项目?目录如何用IDEA2022创建并初始化一个SpringBoot项目?0. 环境说明1.  创建SpringBoot项目 2.编写初始化代码0. 环境说明IDEA2022.3.1JDK1.8SpringBoot1.  创建SpringBoot项目        打开IDEA,选择NewProject创建项目。        填写项目名称、项目构建方式、jdk版本,按需要修改项目文件路径等信息。        选择springboot版本以及需要的包,此处只选择了springweb。        此处需特别注意,若你使用的是jdk1

  9. ruby-on-rails - 您已经激活了 spring 1.3.6,但是您的 Gemfile 需要 spring 1.3.3。 ( gem ::加载错误) - 2

    我今天遇到了同样的问题,有一个建议:在您的命令前添加bundleexec可能会解决此问题。前置bundleexec没有帮助(我已经这样做了)。springstop和springrestart没有帮助。我需要做的:bundleupdatespring这对我有用。在之前的gemlock文件中使用spring版本是否有更好的解决方案? 最佳答案 我删除gemfile.lock并运行bundle通常会清除一切。否则只需从Gemfile中删除gem"spring"并运行bundle 关于ruby-

  10. Slowloris DoS攻击的原理与简单实现 - 2

    前言    Slowloris攻击是我在李华峰老师的书——《MetasploitWeb 渗透测试实战》里面看的,感觉既简单又使用,现在这种攻击是很容易被防护的啦。不过我也不敢真刀实战的去试,只是拿个靶机玩玩罢了。         废话还是写在结语里面吧。(划掉)结语可以不看(划掉)Slowloris攻击的原理        Slowloris是一种资源消耗类DoS攻击,它利用部分HTTP请求进行操作。也叫做慢速攻击,这里的慢速并不是说发动攻击慢,而是访问一条链接的速度慢。Slowloris攻击的功能是打开与目标Web服务器的连接,然后尽可能长时间的保持这些连接打开。如果由多台电脑同时发起Slo

随机推荐