zoukankan      html  css  js  c++  java
  • Spring 框架的概述以及Spring中基于XML的IOC配置

    Spring 框架的概述以及Spring中基于XML的IOC配置

    一、简介

    1. Spring的两大核心:IOC(DI)与AOP,IOC是反转控制,DI依赖注入
    2. 特点:轻量级、依赖注入、面向切面编程、容器、框架、一站式
    3. 优势:
      1. 方便解耦:做到编译期不依赖,运行期才依赖
      2. AOP的支持
      3. 声明式事务的支持
      4. 方便程序的测试
      5. 方便整合各种框架
      6. 降低JavaEE API的使用难度
      7. Spring源码很厉害

    解耦:

    • 耦合包括:类之间的和方法之间的

    • 解决的思路:

      1. 在创建对象的时候用反射来创建,而不是new
      2. 读取配置文件来获取要创建的对象全限定类名
    • Bean:在计算机英语中有可重用组件的含义

    • javabean(用java语言编写的可重用组件)>实体类

    二、工厂类解耦

    在类中直接new的方法,耦合性太过于高,那么不如将这件事情交给一个工厂类来解决。

    以下,我们将为所有的Bean创建一个工厂类,BeanFactory。

    /**
     * Bean:可重用组件
     */
    public class BeanFactory {
       private static Properties props;
        //静态代码块
        static{
            try {
                //1.实例化Properties对象
                props=new Properties();
                //2.获取Properties文件的流对象
                InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
                props.load(in);
            }
            catch (Exception e){
                throw new ExceptionInInitializerError("初始化properties失败");
            }
    
        }
    }
    

    BeanFactory初始化时,将从配置文件bean.properties中,获取Properties元素。

    接下来实现getBean方法,根据Properties方法获取组件路径,并创建对象。

    /**
         * 根据bean的名称获取bean对象
         * @param beanName
         * @return
         */
        public static Object getBean(String beanName){
            Object bean = null;
    
            try {
                String beanPath = props.getProperty(beanName);
                bean = Class.forName(beanPath).newInstance();
            }catch (Exception e){
                e.printStackTrace();
            }
    
            return bean;
        }
    

    以后就可以使用BeanFactory的类方法进行对象创建。

    //    IAccountDao accountDao=new AccountDaoImpl();
        IAccountDao accountDao = (IAccountDao) BeanFactory.getBean("accountDao");
    

    三、单例模式

    然后有一个问题是:每次调用getBean方法,我们都会创建一个BeanFactory对象,这里完全可以替换成单例模式。

    在BeanFactory中定义一个Map容器,存放我们需要创建的对象

    private static Map<String,Object> beans;
    

    接下来这样修改就能得到单例效果。

    /**
     * Bean:可重用组件
     */
    public class BeanFactory {
        private static Properties props;
    
        //容器
        private static Map<String,Object> beans;
    
        //静态代码块
        static{
            try {
                //1.实例化Properties对象
                props=new Properties();
                //2.获取Properties文件的流对象
                InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
                props.load(in);
                //3.容器实例化
                beans = new HashMap<String, Object>();
                //4.从配置文件中取出所有的key
                Enumeration<String> keys = (Enumeration)props.keys();
                //5.遍历枚举
                while(keys.hasMoreElements()){
                    //取出每个key
                    String key = keys.nextElement();
                    //根据key获取value
                    String beanPath = props.getProperty(key);
                    Object value = Class.forName(beanPath);
                    //存放容器
                    beans.put(key,value);
                }
            }
            catch (Exception e){
                throw new ExceptionInInitializerError("初始化properties失败");
            }
    
        }
    
        /**
         * 根据bean的名称获取bean对象
         * @param beanName
         * @return
         */
    //    public static Object getBean(String beanName){
    //        Object bean = null;
    //
    //        try {
    //            String beanPath = props.getProperty(beanName);
    //            bean = Class.forName(beanPath).newInstance();
    //        }catch (Exception e){
    //            e.printStackTrace();
    //        }
    //
    //        return bean;
    //    }
        public static Object getBean(String beanName){
            return beans.get(beanName);
        }
    }
    

    四、IOC(反转控制 Inversion of Control)

    //        IAccountService accountService=new AccountServiceImpl();
            IAccountService accountService = (IAccountService) BeanFactory.getBean("accountService");
    

    这两行代码的区别很能体现出IOC的思想。

    区别:

    • 一般情况:App直接向各种资源进行请求
    • IOC:App向工厂进行请求,工厂与资源进行联系,工厂控制资源。

    五、Spring中的IOC

    以上是我们自己实现的IOC,这一切如果使用Spring的话,它将帮我们解决,所以我们学会了IOC的原理,接下来学Spring的用法。

    删除掉上面的BeanFactory,这个由Spring来做。

    • 在pom.xml中导入spring
    <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.0.2.RELEASE</version>
    </dependency>
    
    • 在resources下创建beans.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    </beans>
    

    创建bean:(bean标签的tag ”id“写bean的名字,”class“写bean的全限定类名)

        <bean id="accountDao" class="com.mmj.dao.impl.AccountDaoImpl"></bean>
        <bean id="accoutService" class="com.mmj.service.impl.AccountServiceImpl"></bean>
    
    • 初始化容器
    ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
    

    note:要用Spring的5.0.2版本,其他版本代码不太一样。

    public class Client {
        /**
         * 获取Spring的ioc。根据id获取对象
         * @param args
         */
        public static void main(String[] args) {
    //        IAccountService accountService=new AccountServiceImpl();
            //1. 获取核心容器对象
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            IAccountService accountService = (IAccountService) context.getBean("accountService");
            System.out.println(accountService);
            IAccountService accountService2 = (IAccountService) context.getBean("accountService");
            System.out.println(accountService2);
            //accountService.saveAccount();
        }
    }
    

    输出结果

    com.mmj.service.impl.AccountServiceImpl@58134517
    com.mmj.service.impl.AccountServiceImpl@58134517
    

    5.1 ApplicationContext三个常用实现类

    1. ClassPathXmlApplicationContext:加载类路径下的配置文件
    2. FileSystemXmlApplicationContext:加载磁盘任意位置文件(有权限)
    3. AnnotationConfigApplicationContext:它是用于读取注解创建容器的

    但Spring的容器ApplicationContextBeanFactory有一些不同。

    • ApplicationContext创建容器使用的策略是立即加载的方式,也就是一读取配置文件,就马上创建配置中的文件。
    • BeanFactory创建容器的时候,使用的是延迟加载的方式。也就是什么时候根据id创建对象了,才是真正创建对象的时候。
        public static void main(String[] args) {
    ////        IAccountService accountService=new AccountServiceImpl();
    //        //1. 获取核心容器对象
    //        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    //        IAccountService accountService = (IAccountService) context.getBean("accountService");
    //        System.out.println(accountService);
    //        IAccountService accountService2 = (IAccountService) context.getBean("accountService");
    //        System.out.println(accountService2);
    //        //accountService.saveAccount();
            Resource resource = new ClassPathResource("beans.xml");
            BeanFactory beanFactory = new XmlBeanFactory(resource);
            IAccountService accountService = (IAccountService) beanFactory.getBean("accountService");
            System.out.println(accountService);
        }
    }
    

    这两者的区别在于:

    1. ApplicationContext在new的时候就已经初始化对象了,也就是在读取配置文件后就开始创建了。
    2. BeanFactory加载完配置文件还没有创建对象,而是在调用getBean,使用到对象的时候才开始创建。

    因此:ApplicationContext适用于单例模式(更多),BeanFactory适用于多例模式

    5.2 Spring中对Bean的管理细节

    1. 创建bean的三种方式

    <!--第一种方式,使用组件默认构造函数创建,如果没有默认构造函数就会报错-->
    <bean id="accountDao" class="com.mmj.dao.impl.AccountDaoImpl"></bean>
    
    <!--第二种方式,使用普通工厂方法创建对象(使用某个类中的方法创建对象,并且存入容器)-->
    <bean id="beanFactory" class="com.mmj.factory.InstanceFactory"></bean>
    <bean id="accountDao" factory-bean="beanFactory" factory-method="getDao"></bean>
    
    <!--第三种方式,使用工厂中的静态方法创建-->
    <bean id="accountDao" class="com.mmj.factory.StaticFactory" factory-method="getStaticDao"></bean>
    

    2. bean对象的作用范围

    3. bean对象的生命周期

    keep going
  • 相关阅读:
    Android 工程师进阶 34 讲
    300分钟搞定数据结构与算法
    即学即用的Spark实战44讲
    42讲轻松通关 Flink
    Webpack原理与实践
    大数据运维实战
    ZooKeeper源码分析与实战
    前端高手进阶
    重学数据结构与算法
    ElementUI中el-upload怎样上传文件并且传递额外参数给Springboot后台进行接收
  • 原文地址:https://www.cnblogs.com/MarkKobs-blog/p/11332397.html
Copyright © 2011-2022 走看看