• 小白学习spring第一天


    第二章:Spring

    第1节:概述

    1.1 介绍 heap stack
    Spring是一个分层的Java SE/EE full-stack(一站式)轻量级开源框架,以 IoCInverse Of Control:控制反转)和 AOP(Aspect Oriented Programming:面向切面编程)为内核。
    在java三层架构当中分别提供了相应技术:
    表现层(web层)      :SpringMVC 框架,servlet
    业务层(service层)  :Bean管理(IOC容器,在三层都有体现) 声明式事务
    持久层(dao层)      :JdbcTemplate模板对象以及提供了ORM模块整合其他优秀的持久层技术
    
    spring 框架: 
    分层一站式框架  轻量   开源 
    AOP IOC
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    1.2 发展历程
    1997 年, IBM提出了EJB 的思想
    1998 年,SUN制定开发标准规范 EJB1.0
    1999 年,EJB1.1 发布
    2001 年,EJB2.0 发布
    2003 年,EJB2.1 发布
    2006 年,EJB3.0 发布
    
    Rod JohnsonSpring 之父)
    Expert One-to-One J2EE Design and Development(2002)
    阐述了 J2EE 使用EJB 开发设计的优点及解决方案
    Expert One-to-One J2EE Development without EJB(2004)
    阐述了 J2EE 开发不使用 EJB的解决方式(Spring 雏形)
    
    20179 月份发布了 Spring 的最新版本 Spring5.0 通用版(GA)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1.3 优势
    1. 方便解耦,简化开发:Spring 就是一个大工厂,可以管理所有对象的创建和依赖关系维护,交给Spring管理
    2. AOP 编程的支持:可以方便的实现对程序进行权限拦截,日志记录,运行的监控
    3. 声明式事务的支持:通过配置方式完成对事务的管理,无需手动编程
    4. 方便程序的测试:对Junit支持,可以通过注解方便的对Spring程序进行测试
    5. 整合外部优秀技术:Spring内部提供了对各种优秀框架(HibernateMybatisQuartz等)的直接支持
    6. javaEE技术的封装 :Spring对javaEE开发当中复杂难用的API(JavaEmail, RMI等)进行封装,降低了这些API的使用难度。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1.4 体系结构
      Spring的核心是容器(IOC):  Beans Core Context SpEL表达式
      中间层技术:AOP Aspects AOP
      web: servler  springmvc 
      data Access: 数据访问层: jdbc  ORM 整合外部的优秀框架 Transaction 事务
      基于Test测试: spring 整合junit junit4.X 
      
      官方网站: 
      https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#spring-core
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    第2节:程序的耦合和解耦合

    2.1 什么是程序的耦合
    话术:
    程序的耦合是程序之间的关联性,也就是多个类的联系是否紧密,多个对象之间的关系是否密切。
    
    耦合度高: 
    (1)不利于扩展
    (2)不利于程序的维护。
    
    生活中的案例: 
    你的房子里面有窗子,那么房子和窗子就有了关联
    
    	耦合度是松还是紧就看你的关联是强还是弱,也就是修改的代价,比如你窗子是扣死在墙里的那么你修改窗子就必须修改墙 这就比较紧密了,反应在程序上就是耦合度高,不利于程序的扩展和维护。
    	但是如果你窗子是按照某种规格的 可以自由拆装的,那么修改的代价就小,耦合度也就低了,反应在程序上就是耦合度低,利于程序的扩展和维护。
    
    我们写程序的目标就是 高内聚 低耦合!
    这样修改起来 就不会有太多的联系,不用改一个地方其他的都要修改。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    2.2 解决程序耦合的思路
    2.2.1 编译不依赖,运行时才依赖
    当我们讲解jdbc时,是通过反射来注册驱动的,代码如下:
    
    • 1
    Class.forName("com.mysql.jdbc.Driver");//使用的驱动类是指定了一个字符串
    底层: DriverManager.regist(new com.mysql.jdbc.Driver());
    Connection connection = DriverManager.getConnection("","","");
    
    • 1
    • 2
    • 3
     	此时的好处式,我们的类中在编译阶段不再需要具体的驱动类,就算删除mysql的驱动jar包,依然可以通过编译。在运行阶段才会依赖驱动包。实际开发当中,我们应该做到编译不依赖,运行时才依赖。
      上述代码产生的新问题,mysql驱动类的全限定类名作为一个字符串java类中是写死的,一旦发生改变,还需要修改源码。
    
      使用配置文件结合反射就可以解决上述问题。      
    
    • 1
    • 2
    • 3
    • 4
    2.2.2 使用工厂模式解耦合
     在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的 方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。 
    
    那么,这个读取配置文件,创建和获取三层对象的类就是工厂。
    
    service 调用dao:  
    
    原生:  new xxxDaoImpl();  问题: service实现类当中出现了 new关键字, 出现了dao 层具体的实现类。 不满足java设计原则: 面向接口开发~  总结: 耦合度高~ 
    
    工厂模式: XXXFactory.getInstance(); 获得接口的实现类: xxxDao接口接收~  解决了: new关键字, 业务层的实现类当中, 不在出现dao层的实现类。  总结: 松耦合~ 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    第3节:IOC 机制

    3.1 IOC的简介
    SpringIOC:IOC 是 Inversion of Control 的缩写,多数书籍翻译成“控制反转”,还有些书籍翻译成为“控制反向”或者“控制倒置”。
    
    就是将对象的创建和维护的权利交给spring 框架。 
    
    1996 年,Michael Mattson 在一篇有关探讨面向对象框架的文章中,首先提出了 IOC 这个概念。简单来说就是把复杂系统分解成相互合作的对象,这些对象类通过封装以后,内部实现对外部是透明的,从而降低了解决问题的复杂度,而且可以灵活地被重用和扩展。
    
    IOC 理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦 如下图
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    		大家看到了吧,由于引进了中间位置的“第三方”,也就是IOC容器,使得ABCD4个对象没有了耦合关系,齿轮之间的传动全部依靠“第三方”了, 全部对象的控制权全部上缴给“第三方”IOC容器,所以,IOC容器成了整个系统的关键核心,它起到了一种类似“粘合剂”的作用,把系统中的所有对象粘合 在一起发挥作用,如果没有这个“粘合剂”,对象与对象之间会彼此失去联系,这就是有人把IOC容器比喻成“粘合剂”的由来。
    我们再来做个试验:把上图中间的IOC容器拿掉,然后再来看看这套系统:
    
    • 1
    • 2

    在这里插入图片描述

    		我们现在看到的画面,就是我们要实现整个系统所需要完成的全部内容。这时候,ABCD4个对象之间已经没有了耦合关系,彼此毫无联系,这样的话, 当你在实现A的时候,根本无须再去考虑BCD了,对象之间的依赖关系已经降低到了最低程度。所以,如果真能实现IOC容器,对于系统开发而言,这将是 一件多么美好的事情,参与开发的每一成员只要实现自己的类就可以了,跟别人没有任何关系!
    
    总结: 
    	IOC容器就是创建对象, 并且维护对象和对象之间的关联关系。
    
    • 1
    • 2
    • 3
    • 4
    3.2 IOC作用
    		IOC本质上就是一个大工厂,大容器。主要作用就是创建和管理对象的依赖关系,削减计算机程序的耦合(解除我们代码中的依赖关系),提高程序的可扩展性和可维护性。
    
    • 1
    3.3 IOC入门
    3.3.1 构建工程添加依赖
    <properties>
            <spring.version>5.2.5.RELEASEspring.version>
        properties>
        
        <dependencies>
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-contextartifactId>
                <version>${spring.version}version>
            dependency>
        dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    3.3.2 创建持久层接口和实现类
    public interface UserDao {    
        public void save();
    }
    
    public class UserDaoImpl implements UserDao {
        @Override
        public void save() {
            System.out.println("userDao save method running...... ");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    3.3.3 创建业务层接口和实现类
    public interface UserService {    
        public void saveService();
    }
    
    public class UserServiceImpl implements UserService {
        @Override
        public void saveService() {
            System.out.println("userSerivce save method running......");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    3.3.4 创建IOC配置文件
    xml文件名称: applicationContext.xml ,注意文件名称不是必须
    
    • 1
    <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">
    
    beans>
    
    • 1
    • 2
    • 3
    3.3.5 配置文件管理对象
    
    <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="userDao" class="com.ujiuye.dao.impl.UserDaoImpl">bean>
        
        <bean id="userService" class="com.ujiuye.service.UserServiceImpl">bean>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    3.3.6 测试
        @Test
        public void test1(){
            //1:获得spring IOC容器对象:
            ApplicationContext applicationContext =
                    new ClassPathXmlApplicationContext("applicationContext.xml");
            //2:从容器当中根据id获得UserDaoImpl 对象,执行userDao对象的save方法
            UserDao userDao = (UserDao) applicationContext.getBean("userDao");
            userDao.save();
            //3:从容器当中根据id获得UserServiceImpl 对象,执行userService对象的saveService方法
            UserService userService = (UserService)applicationContext.getBean("userService");
            userService.saveService();
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    运行结果: 
    
    • 1

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zu3nHWrz-1666881307897)(.\images\运行结果1.png)]

    第4节:基于XML的IOC

    4.1 IOC配置文件详解
    bean标签: 用于配置对象交给Spring 来创建。
    默认情况下他会调用类中无参数的构造器,如果没有无参数构造器则不能成功创建 
    基本属性: 
    id      :  Bean实例对象在Spring容器当中的唯一标识
    class   :  Bean的全限定类名
    name    :  了解,给对象命名操作
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    4.2 源码解析
    4.2.1 IOC容器解析(面试题目)
    IOC思想基于IOC容器完成,IOC容器底层就是对象工厂,Spring 中工厂的类结构图如下:
    
    • 1

    在这里插入图片描述

    1. BeanFactory :该接口是顶层接口, IOC容器的基本实现,是Spring内部使用的接口,不提供开发人员使用,加载配置文件时,不会创建对象,在获得(使用)对象时才采取创建对象。对象的创建时机,getBean()创建【稍后演示】
    
    2. HierarchicalBeanFactory:这个工厂接口非常简单,实现了Bean工厂的分层。 工厂接口也是继承自BeanFacotory,也是一个二级接口,相对于父接口,它只扩展了一个重要的功能——工厂分层
    
    3. AutowireCapableBeanFactory:该接口有自动装配能力,需要注意的是,ApplicationContext接口并没有实现此接口,因为应用代码很少用到此功能,如果确实需要的话,可以调用ApplicationContext的getAutowireCapableBeanFactory方法,来获取此接口的实例。 
    
    4. ListableBeanFactory:获取bean时,Spring 鼓励使用这个接口定义的api,如查看Bean的个数、获取某一类型Bean的配置名、查看容器中是否包括某一Bean等方法。
    
    5. ApplicationContextBeanFactory接口的子接口,提供更多强大的功能,一般由开发人员使用.接口提供了bean基础性操作同时,扩展了国际化等功能。ApplicationContext接口在加载配置文件时候就会配置文件当中的对象进行创建,存放在IOC容器当中
    
    6. AnnotationConfigApplicationContext:   
       当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。
    
    7. ClassPathXmlApplicationContext: 
       它是从类的根路径下加载配置文件 推荐使用这种
    
    8. FileSystemXmlApplicationContext: 
       它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    重点掌握: BeanFactory ApplicationContext
    
    面试题目:  BeanFactory & ApplicationContext 联系和区别: 
    
    BeanFactory : 顶层接口, 接口当中实现了基础性的功能。 提供给框架设计者使用。 
    
                                 加载配置文件的时候, 对象不创建。 getBean();才会创建对象。 
    
    ApplicationContext :是BeanFactory 接口的子接口。 提供了基础性功能之外, 功能进行了扩展,开发者使用。
    
                                  加载配置文件的时候, 对象就创建成功, 并且存放在IOC 容器当中。 
    
    ClassPathXmlApplicationContext: 从类路径下获得资源文件。 
    
    AnnotationConfigApplicationContext: 基于主机模式使用的实现类。 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    第5节:手动实现自己的IOC容器

    5.1 分析IOC 实现思路
    思路:
     1、创建工厂对象,加载Spring核心配置文件
     2、使用xml解析技术,获得bean标签当中id属性以及class属性对应的值
     3、底层使用反射技术,创建对象
     4、准备临时容器,存放创建的对象
     5、提供getBean方法,对外提供对象
     6、测试自定义的工厂对象
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    5.2 设计接口、类和配置文件
    //设定UserDao接口
    public interface UserDao {
        public void save();
    }
    //设定UserDao接口实现类
    public class UserDaoImpl implements UserDao {
        @Override
        public void save() {
            System.out.println("userDao save method running...... ");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    5.3 配置文件
    
    
        
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    5.4 解析配置文件
    dom4J, jdom sax jaxp 解析器
    
    <dependency>
        <groupId>dom4jgroupId>
        <artifactId>dom4jartifactId>
        <version>1.6.1version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    /**
     * 创建自己的工厂类
     */
    public class MyBeanFactory {
    
        //创建一个map集合,模拟IOC容器
        private static Map<String,Object> map = new HashMap<>();
    
        static{
            try {
                //使用dom4J 解析xml文件:
                //第一步:获得一个解析器:
                SAXReader reader = new SAXReader();
                //第二: 读取外部的配置文件:
                String path = "src/main/resources/myApplicationContext.xml";
                //第三: 读取了整个文档对象
                Document document = reader.read(path);
                //第四: 获得根节点:
                Element rootElement = document.getRootElement();//beans
                //第五: 获得根节点下的所有的bean 标签对应的节点:
                List<Element> bean = rootElement.elements("bean");// bean
                for (Element element : bean) {
                    //获得id属性对应的值:
                    String id1 = element.attributeValue("id");
                    //获得class属性对应的值:【全限定类名】
                    String aClass = element.attributeValue("class");//获得class对应的值: 全限定类名。
                    //通过反射创建对象:
                    Class  clz = Class.forName(aClass);
                    Object object = clz.newInstance();
                    //存容器 id做key,创建出来的对象value
                    map.put(id1,object);
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 根据id从容器当中获得对象
         * @param id id的名称
         * @return 返回Object类型对象
         */
        public static Object getBean(String id){
            Object o = map.get(id);
            return o;
        }
    
    }
    
    总结: IOC容器自定义时候; 
    xml解析技术: 
    反射技术
    工厂模式
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    5.5 测试
    @Test
    public void testMyFactory(){
        //1:创建工厂对象
        MyBeanFactory factory =new MyBeanFactory();
        //2:从容器当中根据id获得对象
        UserDao userDao = (UserDao) factory.getBean("userDao");
        System.out.println(userDao);
        userDao.save();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    运行结果: 
    
    • 1

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xHx59dsX-1666881307900)(./images/运行结果2.png)]

    第6节:管理bean细节

    6.1 bean实例化介绍
    bean 对象创建~ 
    
    • 1
    6.2 bean实例化方式【面试问题】
    6.2.1 构造方法的方式
    它会根据默认无参构造函数来创建类对象。如果 bean 中没有默认无参构造函数,将会创建失败
    
    • 1
    (1)创建User类
    public class User implements Serializable {
        public User(){
            System.out.println("user created...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    (2)配置容器管理对象
    
    <bean id="user" class="com.ujiuye.pojo.User">bean>
    
    • 1
    • 2
    (3)测试实例化对象
        @Test
        public void testUser(){
            ApplicationContext context =
                    new ClassPathXmlApplicationContext("applicationContext.xml");
            User user = (User) context.getBean("user");
            System.out.println(user);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    6.2.2 静态工厂方式
    (1)创建静态工厂
    public class ItemFactory {
    
        //静态方法返回实例bean
        public static User createUser(){
            System.out.println("static method running create bean ......");
            return new User();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    (2)配置容器管理对象
    
    <bean id="user" class="com.ujiuye.factory.ItemFactory" factory-method="createUser">bean>
    
    • 1
    • 2
    • 3
    • 4
    (3)测试实例化对象
        @Test
        public void testItemFactory(){
            ApplicationContext context =
                    new ClassPathXmlApplicationContext("applicationContext.xml");
            User user = (User) context.getBean("user");
            System.out.println(user);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    6.2.3 实例工厂方式
    (1)创建实例工厂
    public class NewItemFactory {
        //工厂的非静态方法返回bean实例
        public User createUser(){
            System.out.println("Dynamic method running create bean ......");
            return new User();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    (2)配置容器管理对象
    
     <bean id="itemFactory" class="com.ujiuye.factory.NewItemFactory">bean>
     <bean id="user" factory-bean="itemFactory" factory-method="createUser">bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    (3)测试实例化对象
        @Test
        public void testNewItemFactory(){
            ApplicationContext context =
                    new ClassPathXmlApplicationContext("applicationContext.xml");
            User user = (User) context.getBean("user");
            System.out.println(user);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    6.3 bean作用域【面试问题】
    6.3.1 bean作用域介绍
    
    所谓Bean的作用域其实就是指Spring给我们创建出的对象的存活范围,在配置文件中通过bean的scope属性指定
    <bean id="" class="" scope="">
    scope:指对象的作用范围,取值如下: 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    取值范围说明
    singleton默认值,单例的
    prototype多例的
    requestWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中
    sessionWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中
    global sessionWEB 项目中,应用在 Portlet 环境,如果没有 Portlet 环境那么globalSession 相当于 session
    6.3.2 bean作用域的解析
    (1)scope取值为singleton
     Bean的实例化个数:1Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
    
    • 1
    • 2
    • 3
    (2)scope取值为prototype
     Bean的实例化个数:多个
     Bean的实例化时机:当调用getBean()方法时实例化Bean 
    注意: 多例对象,不会随容器而创建, 不会随容器销毁而销毁。 
    	在内存当中, 由垃圾回收器定期回收~
    
    • 1
    • 2
    • 3
    • 4
    (3)Scope取值为其他值
    scope指定为其他值,需要在特定的环境下使用, 只需要作为一个了解知识,面试能够回答出来即可
    
    • 1
    6.4 bean的生命周期
    6.4.1 bean生命周期介绍
    在这里所谓的Bean的生命周期其实指的是Bean创建到销毁的这么一段时间。 
    在Spring中可以通过配置的形式,指定bean在创建后和销毁前要调用的方法。
    属性:
    init-method:指定bean在创建后调用的方法
    destroy-method:对象在销毁前调用的方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    <bean id="xxx" class="xxx" init-method="" destroy-method="">bean>
    
    • 1
    6.4.2 单例对象的生命周期
    (1)添加方法init和destory
    public class UserServiceImpl implements UserService {
        public void init(){
            System.out.println("init method running...");
        }
        @Override
        public void saveService() {
            System.out.println("userSerivce save method running......");
        }
    
        public void destroy(){
            System.out.println("destroy method running...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    (2)配置文件中配置UserService
    
    <bean id="userService" class="com.ujiuye.service.UserServiceImpl" init-method="init" destroy-method="destroy">
        
    bean>
    
    • 1
    • 2
    • 3
    • 4
    (3)测试单例对象生命周期
    @Test
        public void test1(){
            ClassPathXmlApplicationContext applicationContext =
                    new ClassPathXmlApplicationContext("applicationContext.xml");
            UserService userService = (UserService) applicationContext.getBean("userService");
            userService.saveService();
            //关闭工厂:
            applicationContext.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    单例对象总结: 
    
    对象创建:当应用加载,创建容器时,对象就被创建了
    
    对象运行:只要容器在,对象一直活着
    
    对象销毁:当应用卸载,销毁容器时,对象就被销毁了
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    6.4.3 多例对象的生命周周期
    (1)配置文件scope属性
     
     <bean id="userService" class="com.ujiuye.service.UserServiceImpl" init-method="init" destroy-method="destroy" scope="prototype">bean>
    
    • 1
    • 2
    (2)测试多例对象生命周期
    @Test
    public void test1(){
        ClassPathXmlApplicationContext applicationContext =
            new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.saveService();
        //关闭工厂:
        applicationContext.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    多例对象总结: 
    
    对象创建:当使用对象时(getBean),创建新的对象实例
    
    对象运行:只要对象在使用中,就一直活着
    
    对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了, 对destroy-method属性针对多例不生效。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    第7节:依赖注入

    7.1 介绍
    
    依赖注入(Dependency Injection):简称DI,它是 Spring 框架核心 IOC 的具体实现。
    在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。
    IOC 解耦只是降低他们的依赖关系,但不会消除。
    例如:业务层仍会调用持久层的方法。
    那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。
    简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取
    
    简单理解: 依赖注入就是spring IOC 容器在创建对象的时候, 给属性赋值。 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    7.2 依赖注入方式
    7.2.1 构造函数注入
    (1)创建实体类
    	顾名思义,就是使用类中的构造函数,给成员变量赋值。注意,赋值的操作不是我们自己做的,而是通过配置
    的方式,让 Spring 框架来为我们注入。具体代码如下
    
    • 1
    • 2
    public class Account {
        private String name;
        private Integer age;
        private Date birthday;
    
        public Account(String name, Integer age, Date birthday) {
            this.name = name;
            this.age = age;
            this.birthday = birthday;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    (2)配置文件管理类
    
    <bean id="now" class="java.util.Date">bean>
    <bean id="account" class="com.ujiuye.pojo.Account">
        <constructor-arg name="name" value="王达">constructor-arg>
        <constructor-arg name="age" value="20">constructor-arg>
        <constructor-arg name="birthday" ref="now">constructor-arg>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    (3)构造函数注入测试
    @Test
    public void testDI(){
        ClassPathXmlApplicationContext applicationContext =
            new ClassPathXmlApplicationContext("applicationContext.xml");
        Account account = (Account) applicationContext.getBean("account");
        System.out.println("name:"+account.getName()+" age:"+account.getAge()+" birthday:"+account.getBirthday());
        //打印结果: name:王达 age:20 birthday:Thu Feb 04 13:53:45 CST 2021
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    7.2.2 setter注入
    (1)修改类添加setter方法
    顾名思义,就是在类中提供需要注入成员的 set 方法。具体代码如下:
    
    • 1
    public class Account {
        private String name;
        private Integer age;
        private Date birthday;
        
        public Account() {
        }
    
        public Account(String name, Integer age, Date birthday) {
            this.name = name;
            this.age = age;
            this.birthday = birthday;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    (2)注入依赖数据
    
    <bean id="now" class="java.util.Date">bean>
    <bean id="account" class="com.ujiuye.pojo.Account">
        <property name="name" value="张三丰">property>
        <property name="age" value="31">property>
        <property name="birthday" ref="now">property>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    (3)setter注入测试方法
    @Test
    public void testDI(){
        ClassPathXmlApplicationContext applicationContext =
            new ClassPathXmlApplicationContext("applicationContext.xml");
        Account account = (Account) applicationContext.getBean("account");
        System.out.println("name:"+account.getName()+" age:"+account.getAge()+" birthday:"+account.getBirthday());
        //测试结果: name:张三丰 age:31 birthday:Thu Feb 04 14:05:19 CST 2021
    }
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    7.2.3 P名称空间注入
    语法: p:属性名称=“”  
    在xml当中引入p名称空间
    xmlns:p="http://www.springframework.org/schema/p"
    
    语法: 
    <bean id="account" class="com.offcn.pojo.Account" p:name="唐晓飞" p:age="21" p:birthday-ref="birthday">bean>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    7.2.4 SPEL 表达式注入
    
        <bean id="account" class="com.offcn.pojo.Account">
            <property name="name" value="#{'admin'}">property>
            <property name="age" value="#{account.calcullatorAge()}">property>
            <property name="birthday" value="#{birthday}">property>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    7.3 注入集合数据
    7.3.1 添加集合属性
    顾名思义,就是给类中的集合成员传值,它用的也是set方法注入的方式,只不过变量的数据类型都是集合。 
    我们这里介绍注入数组,List,Set,Map,Properties。具体代码如下:
    
    
    • 1
    • 2
    • 3
    public class Account {
        //注入数组,List集合,Set集合,Map集合,Properties集合属性
        private String[] myStrs;
        private List<String> myList;
        private Set<String> mySet;
        private Map<String,String> myMap;
        private Properties myProps;
    
        public Account() {
        }
    
        public String[] getMyStrs() {
            return myStrs;
        }
    
        public void setMyStrs(String[] myStrs) {
            this.myStrs = myStrs;
        }
    
        public List<String> getMyList() {
            return myList;
        }
    
        public void setMyList(List<String> myList) {
            this.myList = myList;
        }
    
        public Set<String> getMySet() {
            return mySet;
        }
    
        public void setMySet(Set<String> mySet) {
            this.mySet = mySet;
        }
    
        public Map<String, String> getMyMap() {
            return myMap;
        }
    
        public void setMyMap(Map<String, String> myMap) {
            this.myMap = myMap;
        }
    
        public Properties getMyProps() {
            return myProps;
        }
    
        public void setMyProps(Properties myProps) {
            this.myProps = myProps;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    7.3.2 注入依赖集合数据
    
    <bean id="account" class="com.ujiuye.pojo.Account">
        
    
        
        <property name="myStrs">
            <array>
                <value>array-AAAvalue>
                <value>array-BBBvalue>
                <value>array-CCCvalue>
            array>
        property>
        
        <property name="myList">
            <list>
                <value>list-AAAvalue>
                <value>list-BBBvalue>
                <value>list-CCCvalue>
            list>
        property>
        
        <property name="mySet">
            <list>
                <value>set-AAAvalue>
                <value>set-BBBvalue>
                <value>set-CCCvalue>
            list>
        property>
        
        <property name="myMap">
            <map>
                <entry key="map-a" value="AAA">entry>
                <entry key="map-b">
                    <value>BBBvalue>
                entry>
            map>
        property>
    
        
        <property name="myProps">
            <props>
                <prop key="pro-a">AAAprop>
                <prop key="pro-b">BBBprop>
            props>
        property>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    7.3.3 集合注入测试方法
    @Test
    public void testDI(){
        ClassPathXmlApplicationContext applicationContext =
            new ClassPathXmlApplicationContext("applicationContext.xml");
        Account account = (Account) applicationContext.getBean("account");
        System.out.println("array:"+ Arrays.toString(account.getMyStrs()));
        System.out.println("list:"+account.getMyList());
        System.out.println("set:"+account.getMySet());
        System.out.println("map:"+account.getMyMap());
        System.out.println("props:"+account.getMyProps());
            /*
            测试结果: 
            array:[array-AAA, array-BBB, array-CCC]
            list:[list-AAA, list-BBB, list-CCC]
            set:[set-AAA, set-BBB, set-CCC]
            map:{map-a=AAA, map-b=BBB}
            props:{pro-b=BBB, pro-a=AAA}
    
             */
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
  • 相关阅读:
    【三大锁】悲观锁——mysql悲观锁
    LeetCode09——回文数
    Redis第十二讲:如何保证数据一致性、缓存设计模式、缓存穿透问题解决
    工欲善其事,必先利其器,五款实用的办公软件推荐
    华为云云耀云服务器L实例评测|华为云云耀云服务器L实例评测使用
    Linux vim的使用。
    【开源】基于Vue.js的智能停车场管理系统的设计和实现
    软件设计模式系列之十五——职责链模式
    leetcode第362场周赛
    what?测试/开发程序员要被淘汰了?年龄40被砍到了32?一瞬间,有点缓不过神来......
  • 原文地址:https://blog.csdn.net/sjxxxx_/article/details/127562275