Spring框架——初学IOC容器

13 篇文章 0 订阅
5 篇文章 0 订阅

注:作者本人也是初学者,所以本文有些总结性见解可能存在问题,但是多数问题都是在上网查询过资料后总结的,如果有逻辑或者原理上的错误,或者见解不同,欢迎在评论区讨论!!!

目录

IOC

1.什么是IOC

1.1什么是控制反转

1.2什么是耦合性

1.2.1有关耦合性在开发中常见的问题

2.IOC底层原理

2.1使用工厂模式解耦

2.2使用IOC容器解耦

3.IOC(接口)

IOC的几个体系 

IOC具体操作:Bean管理

  1.什么是Bean管理

  2.Bean管理操作又两种方式

1)基于xml方式创建对象

2)基于xml方式注入属性

2.1)第一种注入方式:使用set方法注入属性

2.2)第二种注入方式:通过含参构造方法注入属性

2.3)第三种注入方式:p名称空间注入(set方法注入优化)

tips1:注入空值和特殊符号

        注入属性-外部bean

        注入属性-内部注入

        注入属性-级联赋值

2.4)注入集合属性

        细节问题1:集合存储的是一个对象

        细节问题2:把集合注入部分提取出来,而不是普通的标签内置

2.5)自动装配

2.6)引入其他配置文件(分模块开发)

Bean补充1:   FactoryBean

Bean补充2:   Bean作用域

Bean补充3:  Bean的生命周期

        注:关于后置处理器

3)使用注解进行配置

1. 获取类对象(在实现类上配置)

2.在字段上注入属性


IOC

  • IOC底层原理

  • IOC接口(BeanFactory)

  • IOC操作Bean管理(基于xml)

  • IOC操作Bean管理(基于注释)

1.什么是IOC

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

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

(3)做入门案例就是IOC的实现

1.1什么是控制反转

                (1)控制反转并不是什么技术,而是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架(第三方)来管理。

                (2)正控制:需要使用某个对象时,需要自己去负责对象的创建

                (3)反控制:需要使用某个对象时,只需要从Spring容器中获取需要使用的对象,不关心对象的创建过程,将创建对象的控制权反转给Spring框架。

                (4)那这样需要对象的时候就不需要面向其他对象,而是找IOC去要就行了,具体有没有不管我们事(这样就把开发的各个领域区分开来)。负责开发各个领域的人就不需要去找其他类获取对象,各个领域的职能被分割开了。

1.2什么是耦合性

        耦合性(英语:Coupling,dependency,或称耦合力耦合度)是一种软件度量,是指一程序中,模块及模块之间信息或参数依赖的程度。

        内聚性是一个和耦合性相对的概念,一般而言低耦合性代表高内聚性,反之亦然。耦合性和内聚性都是由提出结构化设计概念的赖瑞·康斯坦丁所提出[1]。低耦合性是结构良好程序的特性,低耦合性程序的可读性及可维护性会比较好。

        例子:两个类分别为学生类和计算器类,学生类中有计算方法,其方法体中创建了计算器类并调用了他的计算方法,这样学生类和计算机类中耦合度就太高了。当计算机类的位置改变时,学生类调用计算机类的位置也要跟着改变,当计算器类方法名发生改变时,学生类调用的计算器类方法名也要跟着改变。

1.2.1有关耦合性在开发中常见的问题

         如果我们在开发中,负责后端的人员需要完成Service层的编写,而队友负责UserDao实现类的编写,我们在编写Service层实现类的时候不可避免的会调用UserDao类方法,因此就不可避免的需要创建对象,导入对象所在包。而如果UserDao相应的实现类还没有编写,我们负责Service层的人员无法创建对象,因此就无法继续向下编写,这样的代码结构耦合性极高。这里就诞生了IOC容器,Service把创建对象交给IOC容器,而UserDao把写好的对象配置给IOC,这样编写不同层代码的人就无需关注对方的进度,只需要关注自己的进度即可。

        

2.IOC底层原理

xml解析,工厂模式,反射(反射的目的:通过得到类的字节码文件,可以操作类中的所有内容)

2.1使用工厂模式解耦

        在我们学习完javaweb我们都知道开发时所用到的三层架构,即负责处理请求信息的web层、处理业务的service层和处理数据的dao层。其中Service层需要调用dao层的一个或者多个数据处理方法,这样就不可避免的需要创建dao对象,导入dao包,那么在开发中如果负责编写dao层的人还没有完成代码,那么我们也就无法获取dao对象。

        这时,我们就可以将创建对象的权利交给“别人”,也就是工厂类。

        工厂类最开始无需把真正带有对象的返回值返回回去,只需要返回null(毕竟负责编写dao层的人还没有编写好,既然没有编写好,那么怎么用不存在的dao接口实现类创建对象?),那么编译器就不会报错,service层的人就拿到了dao对象(其实是null),调用接口中已经约束好功能的方法就可以完成service层的逻辑实现。当dao层的人写好代码开始整合的时候,我们再把Factory加工的类方法返回值全部改成实际返回值,这样一来大大加快了开发速度。

                                        Service ——>Factory——>Dao

 

        上述说法多少有些抽象,所以我们来举个生活中很常见的例子吧:

        手机,我们日常中最常见的东西。一部手机有很多部分组成:

        其中芯片的设计需要一个公司负责完成,比如华为海斯的麒麟芯片设计,美国高通的骁龙芯片设计,他们负责的是芯片设计职能,具体怎么做他们是不需要会的,他们只需要按照光刻机厂商提供的芯片制作规格去设计芯片即可。

        而芯片的制作也无需考虑芯片如何设计,他们需要做的就是提高光刻机的精度,如何让光刻机可以制作7nm,5nm甚至4nm芯片,而这些芯片结构如何设计不管他们事。

        芯片设计厂和芯片加工厂之间是各司其职,他们只需要在双方规定的协议之下做他们做的事即可,无需等你突破4nm制作工艺我再去设计4nm芯片,也无需等你会设计4nm芯片我再去突破4nm的制作工艺。这个协议就是负责两方交互的“Factory类”,他将两个本是一个职能的芯片服务分裂为多个,每个方面各司其职。

        但是这样我们发现一个问题:虽然Service和Dao各司其职了,但是Factorty与Dao层的耦合性提高了,Factory需要根据Dao进行反复修改,于是就有了后面的IOC容器来进一步降低耦合性。

2.2使用IOC容器解耦

        IOC容器解耦实际上是工厂类的再升级版本,因为他底层任然使用了工厂类进行相关操作

        1.首先我们把需要创建类的路径都配置在一个文件中

        2.在spring框架下,底层调用方法去读取配置文件中的每个地址,并利用Class进行对象的反射操作,创建对象,并将其安置在工厂类中

        3.需要创建对象的时候,从IOC容器内部的工厂类去取即可

        这样这个配置文件就成为了缓解耦合性的载体,编写程序的时我们也可以给配置文件直接留白,等到所有成员负责的领域都完工后,完善配置文件。

3.IOC(接口)

  • IOC思想基于IOC容器完成,IOC容器底层就是对象工厂

  • Spring提供IOC容器实现两种方式:(两个接口)

    1). BeanFactory:IOC容器基本实现方式,是Spring内部的使用接口,不提供开发人员进行使用 —— 加载配置文件时不会创建对象,在获取对象(使用)才去创建对象

    2). ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用——加载配置文件时,就会把 你在配置文件中配置的对象 进行创建(可以结合tomcat使用,在服务器的init方法中,服务器启动时,就自动加载该配置文件)

 ApplicationContext的两个后代实现类

  • FileSystemXmlApplicationContext类是通过盘符路径加载配置文件

  • ClassPathXmlApplicationContext类是通过类路径加载配置文件

IOC的几个体系 

  1. Resource体系:对资源的抽象,它的每一个实现类都代表了一种资源访问的策略。有了策略那就有加载资源的方法,Spring利用ResourceLoader来进行统一资源加载。

  2. BeanFactory体系:BeanFactory是一个非常纯粹的bean容器,它是IOC必备的数据结构,其中BeanDefinition是他的基本结构,他内部维护着一个BeanDefinition map,并且可以根据BeanDefinition的描述进行bean的创建和管理。

  3. BeanDefinition体系:BeanDefinition用来描述Spring中的Bean对象。

  4. BeanDefinitionReader体系:BeanDefinitionReader的作用是读取Spring的配置文件的内容,并将其转换成ioc容器内部数据结构:BeanDefinition。

  5. ApplicationContext体系:这也就是传说中的Spring容器,它叫做应用上下文,与我们应用息息相关,他继承BeanFactory,所以他是BeanFactory的拓展升级版:

    • 继承MessageSource,提供国际化的标准访问策略

    • 继承ApplicationEvenPublisher,提供强大的事件机制

    • 扩展ResourceLoader,可以用来加载多个Resource,可以灵活访问不同的资源

    • 对Web应用的支持。

IOC具体操作:Bean管理

1.什么是Bean管理

Bean管理指的是两个操作

  • Spring创建对象

  • Spring注入属性

2.Bean管理操作又两种方式

  • 基于xml配置文件方式实现

  • 基于注解方式实现

1)基于xml方式创建对象

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

  2. 在bean标签有很多属性,介绍常用的属性

    id属性:唯一标识

    class属性:类全路径(包类路径)

  3. 创建对象时,默认也是使用对象的无参构造法(当不含无参构造法时会报错)

2)基于xml方式注入属性

  1. DI:依赖注入,就是注入属性

  2. 注入时寻找参数:

    • name属性:通过构造参数名称找到对应参数

    • type属性:通过元素类型注入(同类型字段注入按照注入值顺序注入),type可以省略

    • index属性:通过参数下标找到对应参数

    • value属性:参数值--只包括基本数据类型和String类型

    • ref属性:在bean容器中查找id,将bean容器中的值注入到当前参数

2.1)第一种注入方式:使用set方法注入属性

  • 设置类,设置属性以及set方法

    public class Student {
        private String name;
        private int age;
        private long id;
    ​
        public void setName(String name) {
            this.name = name;
        }
    ​
        public void setAge(int age) {
            this.age = age;
        }
    ​
        public void setId(long id) {
            this.id = id;
        }
        
        public void show(){
            System.out.println(name+"  "+age+"  "+ id);
        }
    }
  • 在配置文件中bean标签内使用property标签进行设置(name和value)

    <bean id="student" class="springStudyDay1.Student">
        <property name="name" value="张三"></property>
        <property name="age" value="18"></property>
        <property name="id" value="2233"></property>
    </bean>
  • 最后在测试类中通过IOC容器提供的ApplicationContext接口加载配置文件,获取加载器对象,最后通过getBean方法获取对象

    public class Demo {
        @Test
        public void DemoStudent(){
            //获取配置文件
            ApplicationContext context = new ClassPathXmlApplicationContext("springUserBean.xml");
            //获取通过加载器对象获得学生对象
            Student st = context.getBean("student",Student.class);
            //使用学生类中的show方法查看属性值是否改变
            st.show();
        }
    }

2.2)第二种注入方式:通过含参构造方法注入属性

  • 创建类,定义属性,创建属性对应有参数构造方法

    public class Book {
        private String name;
        private double price;
    ​
        public Book(String name, double price) {
            this.name = name;
            this.price = price;
        }
    ​
        public void show(){
            System.out.println(name+"  "+price);
        }
    }
  • 在配置文件中进行文件配置这里在bean标签中使用constructor-arg标签

    这里name的设置即可以根据属性名设置值,也可以根据他在构造器中的形参排序顺序设置值

    <bean id="book" class="springStudyDay1.Book">
        <constructor-arg name="name" value="三体"></constructor-arg>
        <constructor-arg name="price" value="49.5"></constructor-arg>
    </bean>
  • 最终在测试类中测试代码运行结果

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

2.3)第三种注入方式:p名称空间注入(set方法注入优化

  • 第一步:修改xml文件配置(将第一行复制,键值后加:p,获取一个名称为p的命名空间,然后在后面的路径中把beans修改为p)

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        
           <bean id="book3" class="com.ling.spring5.Book" p:name="明日方舟" p:author="海猫"></bean>
    </beans>
  • 第二步:配置文件对象(使用bean标签创建对象,使用p:属性 = 值注入属性。)

  • 注意:该方法只能对使用set注入的JavaBean对象生效,使用含参构造器的JavaBean对象无法使用

tips1:注入空值和特殊符号

  • 在设置属性的时候不设置value值,而是在标签体内加上<null/>标签

    <bean id="book4" class="com.ling.spring5.Book">
        <property name="name" value="代码随想录"></property>
        <property name="author" >
            <null/>
        </property>
    </bean>
  • 设置value值时有特殊符号,这时采用xml特有的CDATA语句

    首先把value值单独拿到property内部作为一个标签 ,标签内写上<![CDATA[具体内容]]>,注意value内不要随意加回车,如果添加了,那么回车也会被当做值的一部分

    <bean id="book5" class="com.ling.spring5.Book">
        <property name="name">
            <value><![CDATA[<代码随想录>]]></value>
        </property>
        <property name="author" value="Carl"></property>
    </bean>

注入属性-外部bean

注:之前的注入方法都是注入java已有类,例如String,而对于其他自定义的外部类注入方法我们还不曾知晓,所以此处讲解外部类的注入

  • 创建两个类service类和dao类

  • 在service类中调用dao里面的方法

  • 在spring的配置文件中配置

    <!--首先配置UserDao对象-->
    <bean id="userDao" class="com.ling.spring5.dao.impl.UserDaoImpl"></bean>
    ​
    <!--在有UserDao配置的基础上配置含有userDao作为属性的UserService-->
    <bean id="userService" class="com.ling.spring5.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
        <!--注意,这里ref取代了原本value的位置,其实是引用了对应的 配置对象id 获取配置对象-->
    </bean>

在外部注入中,两个bean是各自各家的两个JavaBean对象配置,只是后者通过id从外部引用了前者,这就是外部注入,外部可以理解为“非包含”。

注入属性-内部注入

  • 和外部注入相似

  • 不同点:主要用于处理一对多的关系,<bean>标签中配置属性<property>时就配置其他对象

    <!--内部bean配置-->
    <bean id="userService2" class="com.ling.spring5.service.impl.UserServiceImpl">
        <property name="userDao">
            <bean id="userDao2" class="com.ling.spring5.dao.impl.UserDaoImpl"></bean>
        </property>
    </bean>

注入属性-级联赋值

其实就是在一个类A中如果有另外一个类a作为自己的属性,那么在配置本类A时,引入的类a就已经给自己的字段附上值,这就是级联赋值。

级联赋值方法

  • 外部注入时,把将要引入的id对应的配置对象设置好字段值,然后在引入,这样在对象创建后,字段对象就已经被初始化,而非一个没设置值的对象。

    <!--首先配置UserDao对象-->
    <!--此处以及配置好了userdao对象,如果有字段配置好字段,那么引用他的类就会获取配置化好的该类-->
    <bean id="userDao" class="com.ling.spring5.dao.impl.UserDaoImpl"></bean>
    ​
    <!--在有UserDao配置的基础上配置含有userDao作为属性的UserService-->
    <bean id="userService" class="com.ling.spring5.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
        <!--注意,这里ref取代了原本value的位置,其实是引用了对应的 配置对象id 获取配置对象-->
    </bean>

  • 内部注入时,把<property>中新定义的<bean>配置文件字段对象赋好值,这样在对象创建后,对象的字段就已经被初始化,而非一个没设置值的对象。

    <!--内部bean配置-->
    <bean id="userService2" class="com.ling.spring5.service.impl.UserServiceImpl">
        <property name="userDao">
            <!--此处配置对象,如果对象有字段则初始化字段,这样外部类就可以直接获取配置好的该类对象-->
            <bean id="userDao2" class="com.ling.spring5.dao.impl.UserDaoImpl"></bean>
        </property>
    </bean>

  • 外部注入时,不初始化将要注入的内容,而是直接赋值

    <!--不初始化内部字段对象-->
    <!--此处未设置部门内容-->
    <bean id="dept" class="com.ling.spring5.domain.Dept"></bean>
    <bean id="person" class="com.ling.spring5.domain.Person">
        <property name="name" value="张三"></property>
        <!--引用未设置字段属性的dept-->
        <property name="dept" ref="dept"></property>
        <!--直接设置字段属性-->
        <property name="dept.name" value="人事管理部"></property>
    </bean>

    注意:这里通过引用来的dept(第一行配置的id),需要直接设置字段,那么就需要拥有他的对象,所以这里需要在源文件中配置好他的get方法。

2.4)注入集合属性

  • 数组配置:配置好对象后配置数组属性,value值用array标签包裹

        <!--数组-->
        <property name="array">
            <array>
                <value>张三</value>
                <value>李四</value>
            </array>
        </property>
  • list集合配置:配置好对象后配置list集合属性,value值用list标签包裹

            <!--list集合-->
            <property name="list">
                <list>
                    <value>张三</value>
                    <value>李四</value>
                </list>
            </property>
  • set集合配置:配置好对象后配置set集合属性,value值用set标签包裹

            <!--set集合-->
            <property name="set">
                <set>
                    <value>张三</value>
                    <value>李四</value>
                </set>
            </property>
  • map集合配置:配置好对象后配置map集合属性,与其他三个不一样,map集合改用entry标签,放在map标签内部,key和value值分别在内部赋值

        <!--map集合配置-->
        <property name="map">
            <map>
                <entry key="1号" value="张三"></entry>
                <entry key="2号" value="李四"></entry>
                <entry key="3号" value="王五"></entry>
            </map>
        </property>
  • properties属性集配置:配置好对象后配置props属性,与其他四个集合不一样,properties标签改用props标签,在props标签内部依次使用prop标签进行键值对配置,key通过属性赋值,而value在标签之间赋值
     <!--属性集配置-->
    <bean id="collection" class="com.ling.spring5.domain.Colloction">
        <property name="properties">
            <props>
                <prop key="name">张三</prop>
                <prop key="friend">李四</prop>
                <prop key="age">19</prop>
            </props>
        </property>
    </bean>
  • 细节问题1:集合存储的是一个对象

    其他的一切按照原list集合配置方式配置,但是当写到value标签时,改用ref标签,将外部的对象id写到ref标签的bean属性中。

    <bean id="user1" class="com.ling.spring5.domain.User">
            <property name="name" value="张三"></property>
        </bean>
    ​
        <bean id="user2" class="com.ling.spring5.domain.User">
            <property name="name" value="李四"></property>
        </bean>
    ​
        <bean id="col" class="com.ling.spring5.domain.Colloction">
            <property name="userList">
                <list>
                    <ref bean="user1"></ref>
                    <ref bean="user2"></ref>
                </list>
            </property>
        </bean>

  • 细节问题2:把集合注入部分提取出来,而不是普通的标签内置

    1.首先配置xml引入的命名空间

    <!--把第一行复制,后加“:util”,后面url后beans命名空间改用util命名空间-->
    <!--把最后一行复制,url中所有的beans改成util-->
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:util="http://www.springframework.org/schema/util"
           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
                               http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    2.然后时配置list对象,整体思路和外部注入类似,首先定义两个user,留出id,定义list时导入id,然后定义对象,把list集合id导入对象属性中。这里糅合了“集合注入自定义的对象”和“外部注入”两个地方

    <!--配置基础类对象-->
    <bean id="user1" class="com.ling.spring5.domain.User">
        <property name="name" value="张三"></property>
    </bean>
    <bean id="user2" class="com.ling.spring5.domain.User">
        <property name="name" value="李四"></property>
    </bean>
    
    <!--使用util命名空间,配置list对象,配置过程几乎和内部配置一样,注意留出id-->
    <util:list id="list1">
        <ref bean="user1"></ref>
        <ref bean="user2"></ref>
    </util:list>
    
    <!--配置对象,配置方法和外部注入一样,在property中使用ref引入外部类-->
    <bean id="listXml" class="com.ling.spring5.domain.ListXml">
        <property name="userList" ref="list1"></property>
    </bean>
    

2.5)自动装配

  1. 什么是自动装配

    根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入

  2. 演示自动装配过程

    第一种:根据属性名称自动注入

    <!--首先配置属性值-->
    <bean id="dept" class="com.ling.spring5.domain.Dept"></bean>
    <!--根据名称自动配置,这里的名称就是类中属性的名称,当在xml中找到与属性名称相同的id时会自动配置属性-->
    <bean id="person1" class="com.ling.spring5.domain.Person" autowire="byName"></bean>

    第二种:根据类型注入

    <!--首先配置属性值-->
    <bean id="dept" class="com.ling.spring5.domain.Dept"></bean>
    <!--根据类型自动配置,这里的类型就是类中属性的类型,当在xml中找到与属性类型相同的配置对象时会自动配置属性-->
    <bean id="person2" class="com.ling.spring5.domain.Person" autowire="byType"></bean>

2.6)引入其他配置文件(分模块开发)

        Spring的配置内容较多,体积较大,可以将Spring根据业务或者模块进行拆分,而在Spring的主配置文件(ApplicationContext对象中传入的文件)中通过import标签进行加载。

Bean补充1:   FactoryBean

Spring有两种类型的bean,一种是普通bean,另外一种是工厂bean(FactoryBean)

  • 普通bean:在配置文件中定义bean类型就是返回类型

    以上学习的都是普通bean创建方式

  • 工厂bean:在配置文件中定于bean类型可以和返回类型不一样

    定义一个Java类,实现FactoryBean接口,重写三个方法,其中getObject方法用于确定该类真正的返回值:

    public class MyBean implements FactoryBean {
        /**
         * 决定工厂bean返回值类型的方法
         * 在使用xml配置文件进行配置时,通过getBean获取Mybean本类对象时,会调用getObject方法并将结果返回
         * @return
         * @throws Exception
         */
        @Override
        public User getObject() throws Exception {
            User user = new User();
            user.setName("张三");
            return user;
        }
    ​
        @Override
        public Class<?> getObjectType() {
            return null;
        }
    ​
        @Override
        public boolean isSingleton() {
            return false;
        }
    }

    xml文件正常书写即可:

    <bean id="myBean" class="com.ling.spring5.domain.MyBean"></bean>

Bean补充2:   Bean作用域

  • 在Spring里面,设置创建bean实例是单实例还是多实例

  • 在Spring里面,默认情况下,bean是单实例对象,即返回的对象都是同一个对象(地址相同)

  • 如何设置单实例还是多实例

    1. 在spring配置文件bean标签里面有属性(scope),用于设置单实例还是多实例

    2. scope属性值

      第一个值 默认值,singleton,表示是单实例对象

      第二个值 prototype,表示是多实例对象,返回的对象地址也就不相同

  • singleton和prototype区别

    1. singleton单实例,prototype多实例

    2. scope设置为singleton时,加载spring配置文件时候就会创建单实例对象

      scope设置为prototype时,不是在加载spring配置文件的时候创建对象,而是在调用getBean方法时创建多实例对象

Bean补充3:  Bean的生命周期

什么是生命周期:从对象创建到对象销毁的过程

  1. 根据配置文件调用对象的无参构造器,创建对象

  2. 根据配置文件调用对象的set方法设置对象属性

  3. 执行后置处理器BeanPostProcessor接口中的postProcessBeforeInitialization前置初始化方法(会对所有配置文件实施)

  4. 执行自己配置的初始化方法,此处在xml需要配置init-method

  5. 执行后置处理器BeanPostProcessor接口中的postProcessAfterInitialization后置初始化方法(会对所有配置文件实施)

  6. 通过ApplicationContext对对象进行操作

  7. 通过ClassPathXmlApplicationContext的close方法关闭容器,执行自己配置的销毁方法,此处在xml需要配置destory-method

注:关于后置处理器

  1. 执行顺序:构造方法—>BeanPostProcessor的before—>init-method—>BeanPostProcessor的after。

  2. 实际运用中,可以配置多个BeanFactoryPostProcessor和BeanPostProcessor

  3. 应用场景

    • 解析bean的注解,将注解中的字段转化为属性

    • 统一将属性在执行前,注入bean中,如数据库访问的sqlMap,如严重服务,这样不需要每个bean都配置属性

    • 打印日志,记录时间等。

 

3)使用注解进行配置

1. 获取类对象(在实现类上配置)

作用在类上,相当于xml配制中添加id,并将该对象放在Bean容器中

  1. @Component:在类上用于实例化Bean

  2. @Controller:使用在web层类上用于实例化Bean

  3. @Service:使用在service层类上用于实例化Bean

  4. @Repository:使用在dao层类上用于实例化Bean

步骤:

1.配置xml注解:使用注解开发,需要在核心配置文件中,指定那个包下的Bean需要进行扫描以识别使用注解配置的类和字段。

<?xml version="1.0" encoding="UTF-8"?>
<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="org.example"></context:component-scan>
</beans>

2.在实现类上使用注解

@Component("userDao")
public class UserDaoImpl implements UserDao {}

3.加载配置文件,从IOC容器中获取对象

public static void main(String[] args) {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("anno.xml");
    UserDao userDao = applicationContext.getBean("userDao", UserDao.class);
    System.out.println(userDao);
}

2.在字段上注入属性

  1. @Autowired使用在字段上用于根据类型依赖注入相当于xml标签中的autowire属性,用于注入属性

    • 使用多态的形式创建对象时,当该字段是自己写的类或接口,且该类的子类或者接口的实现类只有一个被注解过,那么系统就会直接查找到被注解的类,将其注入到其中

    • 使用多态的形式创建对象时,当该字段是自己写的类或接口,且该类的子类或者接口的实现类有多个被注解,那么系统就会查找到所有该接口下被注解的类,根据属性名称比对注解设置的id,并将其注入到bean对象中

  2. @Qualifier配置,结合@Autowired一起用于根据名称进行依赖注入,当遇到多个类注解且id与属性没有一个相同时,使用@Qualifier注解,来指定获取哪个类对象

  3. @Resource,相当于@Autowired和@Qualifier结合,但是此处注解的value属性不等于name属性(name属性并不是最重要的属性),所以需要对name属性进行赋值:@Resource(name = "") ,按名称(id)进行依赖注入,相当于xml标签中的ref属性,用于注入属性

  4. @Scope,作用在类上,标注Bean的作用范围,相当于xml中的scope属性(指定单例singleton还是多例prototype)

  5. @PostConstruct:标注初始化方法,相当于xml中的init-method属性,用于定义初始化方法,在配置好对象之后执行

  6. @PreDestory:标注销毁方法,相当于xml中的destroy-method属性,用于定义销毁方法,在ApplicationContext操作完对象后执行

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Aristocrat l

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值