Spring IOC复习与回顾

IOC
  1. IOC思想基于IOC容器完成,IOC容器底层就是对象工厂,DI(依赖注入)是IOC思想的具体实现

  2. Spring提供IOC容器实现的两种方式:

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

      加载配置文件时候不会创建对象,在获取对象时采取创建对象

    • ApplicatioContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用

      加载配置文件的时候就会把配置文件中的对象进行创建

  3. Bean的作用域

    Spring中Bean默认是单例的,表示对IOC容器中的同一个Bean多次getBean得到的是同一个实例:

       @Test
        public void testStu(){
            ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
            Stu stu = (Stu) context.getBean("stu");
            Stu stu2 = (Stu) context.getBean("stu");
            System.out.println(stu);  //com.dxy.spring5.Stu@17776a8
            System.out.println(stu2); //com.dxy.spring5.Stu@17776a8
        }
    

    当然我们可以通过bean中 scope=”prototype“ 属性设置为多例

    <bean id="stu" class="com.dxy.spring5.Stu" scope="prototype"></bean>
    

    修改后得到的输出为

    @Test
        public void testStu(){
            ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
            Stu stu = (Stu) context.getBean("stu");
            Stu stu2 = (Stu) context.getBean("stu");
            System.out.println(stu);  //com.dxy.spring5.Stu@17776a8
            System.out.println(stu2); //com.dxy.spring5.Stu@69a10787
        }
    

    除此之外,singleton与prototype还有以下区别:

    scope值设置为singleton时,在加载spring配置文件的时候就会创建对象

    scope值设置为prototype时,不会在加载spring配置文件的时候创建对象,而是在调用getBean方法时创建对象(每调一次就会创建一个全新的实例)

  4. Bean的生命周期

    ①通过构造器创建bean实例(无参构造)

    ②为bean 的属性设置值和对其他bean的引用(调用set方法)

    ③调用bean 的初始化方法(需要进行配置初始化的方法)

    ④bean可以使用了(对象获取到了)

    ⑤当容器关闭的时候,调用bean的销毁方法(需要进行配置销毁的方法)

    如果考虑bean的后置处理器,则bean完整的生命周期应该为七步

    ①通过构造器创建bean实例(无参构造)

    ②为bean 的属性设置值和对其他bean的引用(调用set方法)

    ③把bean实例传递给bean后置处理器的方法postProcessBeforeInitialization

    ④调用bean 的初始化方法(需要进行配置初始化的方法)

    ⑤把bean实例传递给bean后置处理器的方法postProcessAfterInitialization

    ⑥bean可以使用了(对象获取到了)

    ⑦当容器关闭的时候,调用bean的销毁方法(需要进行配置销毁的方法)

  5. Bean管理

    Bean管理指的是两个操作:①Spring创建对象;②Spring注入属性

    Bean管理操作有两种方式:①基于xml配置文件方式实现;②基于注解方式实现

    基于xml的实现方式

    <?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:p="http://www.springframework.org/schema/p"
          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--Spring创建对象、注入属性
     每个bean对应一个实例,id的值可以任取,class的值为包类名
     set注入时需要对应类有属性的set方法
     有参构造注入时对应类需要有相应的有参构造器
     -->
    
    <!--  set注入属性  -->
        <bean id="user" class="com.dxy.spring5.User">
            <property name="userName" value="zhangsan"></property>
        </bean>
    
    <!--p空间注入    对set注入的简化,先引入p空间,再注入属性-->
        <bean id="user1" class="com.dxy.spring5.User" p:userName="lisi"></bean>
    
    <!--    有参构造注入属性-->
        <bean id="order" class="com.dxy.spring5.Orders">
            <constructor-arg name="oname" value="box"></constructor-arg>
            <constructor-arg name="address" value="China"></constructor-arg>
        </bean>
    <!--外部bean  使用ref引入id为order的bean对象-->
        <bean id="user2" class="com.dxy.spring5.User">
            <property name="userName" value="zhangsan"></property>
            <property name="orders" ref="order"></property>
            <!--级联赋值  User需要有属性orders的get方法  Orders中需要有set方法 以为这里是有set注入-->
            <property name="orders.oname" value="bottle"></property>
        </bean>
    
    <!--内部bean  order为对象,使用内部bean为其赋值-->
        <bean id="user3" class="com.dxy.spring5.User">
            <!--userName为普通属性   -->
            <property name="userName" value="zhangsan"></property>
            <property name="orders">
                <bean id="order1" class="com.dxy.spring5.Orders">
                    <constructor-arg name="oname" value="computer"></constructor-arg>
                    <constructor-arg name="address" value="China"></constructor-arg>
                </bean>
            </property>
        </bean>
    
    </beans>
    

    集合的属性注入

    <?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:p="http://www.springframework.org/schema/p"
           xmlns:util="http://www.springframework.org/schema/util"
           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-4.0.xsd">
    
        <bean id="stu" class="com.dxy.spring5.Stu">
            <!-- 数组注入   -->
            <property name="courses">
                <array>
                    <value>数学</value>
                    <value>语文</value>
                    <value>历史</value>
                </array>
            </property>
    
            <!--list注入,且元素为对象 -->
            <property name="books" >
                <list>
                    <ref bean="book1"></ref>
                    <ref bean="book2"></ref>
                </list>
            </property>
    
            <!--可以引入util空间,对公共部分进行抽取-->
    <!--        <property name="books" ref="bookList"></property>-->
    
            <!--map注入-->
            <property name="numbers">
                <map>
                    <entry key="zhangsan" value="001"></entry>
                    <entry key="lisi" value="002"></entry>
                </map>
            </property>
    
        </bean>
    
        <util:list id="bookList">
            <ref bean="book1"></ref>
            <ref bean="book2"></ref>
        </util:list>
    
        <bean id="book1" class="com.dxy.spring5.Book">
            <property name="bookName" value="Java并发编程"></property>
        </bean>
        <bean id="book2" class="com.dxy.spring5.Book">
            <property name="bookName" value="深入理解Java虚拟机"></property>
        </bean>
    </beans>
    

    用的实体类:

    User类

    package com.dxy.spring5;
    
    /**
     * Description: <br/>
     * date: 2022/11/15 18:42
     *
     * @author dxy
     * @since JDK 1.8
     */
    public class User {
    
        private String userName;
        private  Orders orders;
    
        public void setUserName(String name){
            this.userName=name;
        }
    
        public void setOrders(Orders orders) {
            this.orders = orders;
        }
    
        public Orders getOrders() {
            return orders;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "userName='" + userName + '\'' +
                    ", orders=" + orders +
                    '}';
        }
    }
    
    

    Orders类

    package com.dxy.spring5;
    
    /**
     * Description: <br/>
     * date: 2022/11/15 19:24
     *
     * @author dxy
     * @since JDK 1.8
     */
    public class Orders {
        private String oname;
        private String address;
    
        public Orders(String oname, String address) {
            this.oname = oname;
            this.address = address;
        }
    
        public void setOname(String oname) {
            this.oname = oname;
        }
    
        @Override
        public String toString() {
            return "Orders{" +
                    "oname='" + oname + '\'' +
                    ", address='" + address + '\'' +
                    '}';
        }
    }
    
    

    Stu类

    package com.dxy.spring5;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    
    /**
     * Description: <br/>
     * date: 2022/11/15 20:43
     *
     * @author dxy
     * @since JDK 1.8
     */
    public class Stu {
        private String[] courses;
        private List<Book> books;
        private Map<String,Integer> numbers;
    
        public void setCourses(String[] courses) {
            this.courses = courses;
        }
    
        public void setBooks(List<Book> books) {
            this.books = books;
        }
    
        public void setNumbers(Map<String, Integer> numbers) {
            this.numbers = numbers;
        }
    
        @Override
        public String toString() {
            return "Stu{" +
                    "courses=" + Arrays.toString(courses) +
                    ", books=" + books+
                    ", numbers=" + numbers +
                    '}';
        }
    }
    

    Book类

    package com.dxy.spring5;
    
    /**
     * Description: <br/>
     * date: 2022/11/15 20:46
     *
     * @author dxy
     * @since JDK 1.8
     */
    public class Book {
        private String bookName;
    
        public void setBookName(String bookName) {
            this.bookName = bookName;
        }
    
        @Override
        public String toString() {
            return "Book{" +
                    "bookName='" + bookName + '\'' +
                    '}';
        }
    }
    
    

    用于测试的类:

    TestSpring5

    package com.dxy.spring5.testdemo;
    
    import com.dxy.spring5.Orders;
    import com.dxy.spring5.Stu;
    import com.dxy.spring5.User;
    import org.junit.Test;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * Description: <br/>
     * date: 2022/11/15 18:31
     *
     * @author dxy
     * @since JDK 1.8
     */
    public class TestSpring5 {
    
    
        @Test
        public void testStu(){
            ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
            Stu stu = (Stu) context.getBean("stu");
            System.out.println(stu);
        }
    
        @Test
        public void testAdd(){
            ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
            User user = (User)context.getBean("user2");
            Orders order = (Orders) context.getBean("order");
            System.out.println(user.toString());
        }
    }
    

    以上我们都是进行手动装配的,即在bean中指定属性以及我们要设置的值,下面我们介绍一下Spring的自动装配

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

    在xml中演示自动装配

    基于byName的自动装配:(在bean中设置autowire=“byName”,此时会根据属性名称来寻找对应id的bean,并将属性值注入)

    <!--这里userName为普通属性,我们用set手动注入,orders为对象,我们使用byName自动装配  注意:此时不许有一个bean的id值与orders属性名称完全一致,才能自动装配成功-->
    <bean id="user" class="com.dxy.spring5.User" autowire="byName">
            <property name="userName" value="zhangsan"></property>
        </bean>
    
        <bean id="orders" class="com.dxy.spring5.Orders">
            <constructor-arg name="oname" value="box"></constructor-arg>
            <constructor-arg name="address" value="China"></constructor-arg>
        </bean>
    

    运行测试类中得到:

    User{userName='zhangsan', orders=Orders{oname='box', address='China'}}
    

    基于byType的自动装配:在bean中设置autowire=“byType”,此时会根据属性的类型来寻找对应class的bean,并将属性值注入)

    <bean id="user" class="com.dxy.spring5.User" autowire="byType">
            <property name="userName" value="zhangsan"></property>
        </bean>
    
        <bean id="orders" class="com.dxy.spring5.Orders">
            <constructor-arg name="oname" value="box"></constructor-arg>
            <constructor-arg name="address" value="China"></constructor-arg>
        </bean>
    

    我们可以得到相同的输出结果。但需要特别注意的是,如果有多个类型相同的bean,我们就不能使用byType来进行自动装配了!

    基于注解的实现方式

    使用注解的目的:简化xml配置

    Spring针对Bean管理中创建对象提供注解:@Component @Service @Controoler @Repository

    上面四个注解功能一致,都可以创建bean实例,只不过我们习惯在不同的层上使用不同的注解,是开发更加规范

    我们先引入了context空间,然后开启组件扫描

    <?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:p="http://www.springframework.org/schema/p"
           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">
    
    <!-- 基于注解实现-->
            <!--开启组件扫描
                方式1.如果扫描多个包,多个包使用逗号隔开
                方式2.扫描包的上层目录-->
        <context:component-scan base-package="com.dxy"></context:component-scan>
    </beans>
    

    创建UserService类,使用注解实现Spring创建对象:

    package com.dxy.spring5.service;
    
    import org.springframework.stereotype.Service;
    
    /**
     * Description: <br/>
     * date: 2022/11/16 10:30
     *
     * @author dxy
     * @since JDK 1.8
     */
    //注解中value属性值可以不写,默认值是类名称首字母小写
    @Service(value = "userService") //等价于<bean id="userService" class="com.dxy.spring5.testdemo.UserService"></bean>
    public class UserService {
        public void print(){
            System.out.println("test...");
        }
    }
    
    @Test
        public void testUserService(){
            ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
            UserService userService = (UserService) context.getBean("userService");
            userService.print(); 
        }
    

    使用注解方式实现属性注入:

    @Autowired:根据属性类型进行自动装配 (使用最多)

    @Qualifier:根据属性名称进行注入,使用@Qualifier时需要和@Autowired一起使用

    @Resource:既可以根据类型注入(使用@Resource),也可以根据名称注入 (使用@Resource(name=“xxx”))

    @Value:可以注入普通属性

    package com.dxy.spring5.service;
    
    import com.dxy.spring5.dao.UserDao;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    /**
     * Description: <br/>
     * date: 2022/11/16 10:30
     *
     * @author dxy
     * @since JDK 1.8
     */
    //注解中value属性值可以不写,默认值是类名称首字母小写
    @Service(value = "userService") //等价于<bean id="userService" class="com.dxy.spring5.testdemo.UserService"></bean>
    public class UserService {
        //在service中注入dao对象,添加注入属性注解
        @Autowired
        private UserDao userDao;
    
        public void print(){
            System.out.println("test...");
            userDao.print();
        }
    }
    

    UserDao

    package com.dxy.spring5.dao;
    
    /**
     * Description: <br/>
     * date: 2022/11/16 10:47
     *
     * @author dxy
     * @since JDK 1.8
     */
    public interface UserDao {
        public void print();
    }
    

    UserDaoImpl

    package com.dxy.spring5.dao;
    
    import org.springframework.stereotype.Repository;
    
    /**
     * Description: <br/>
     * date: 2022/11/16 10:47
     *
     * @author dxy
     * @since JDK 1.8
     */
    @Repository
    public class UserDaoImpl implements UserDao{
    
        public void print() {
            System.out.println("dao test...");
        }
    }
    
    

    完全注解开发

    创建配置类,替代xml配置文件

    package com.dxy.spring5.config;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * Description: <br/>
     * date: 2022/11/16 11:03
     *
     * @author dxy
     * @since JDK 1.8
     */
    @Configuration    //作为配置类,替代xml配置文件
    @ComponentScan(basePackages = {"com.dxy"})
    public class SpringConfig {
    
    }
    

    测试时也有点变化:

     @Test
        public void testUserService1(){
            //加载配置类
            ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
            UserService userService = (UserService) context.getBean("userService");
            userService.print();
        }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值