Spring IOC

Posted Vodka~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring IOC相关的知识,希望对你有一定的参考价值。

一.环境搭建:
-修改Junit版本:

junit
junit
4.12
test

   -修改JDK版本:(可以自行到MVN仓库寻找最新的适用版本)
                        <properties>
						    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
						    <maven.compiler.source>1.8</maven.compiler.source>
						    <maven.compiler.target>1.8</maven.compiler.target>
						  </properties>
						  
    -删除build中的pluginManagement标签。
    -添加Spring 框架的依赖坐标:
                   <dependency>
			         	  <groupId>org.springframework</groupId>
					      <artifactId>spring-context</artifactId>
					      <version>5.3.9</version>
			       </dependency>
   -创建resources目录
   -在 src\\main\\resources 目录下新建 spring.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
       xmlns: 即 xml namespace , xml使用的命名空间;
       xmlns:xsi  即xml schema instance xml 遵守的具体规范;
       xsi:schemaLocation   本文档xml遵守的规范 , 官方指定
-->
</beans>
   -配置bean到xml中,将相应的Bean 纳入到Spring容器来管理。
		<!--
		  id:  bean对象的唯一标识,一般是Bean对象的名称的首字母小写。
		  class:  bean对象的类路径。
		-->
        <bean id="firstSpringTest" class="com.Vodka.service.FirstSpringTest"></bean>
   -加载配置文件,获取实例化对象。

二. Spring IOC 容器 Bean对象实例化模拟:
1.定义Bean 工厂接口,提供获取bean方法
2.定义Bean工厂接口实现类,解析配置文件,实例化Bean对象
3.实现获取Bean方法
4.新建项目,添加dom4j ( XML解析包),以及 jaxen (XML信息语言,可在XML文档中对节点元素进行遍历)等依赖

 <dependency>
       <groupId>dom4j</groupId>
       <artifactId>dom4j</artifactId>
       <version>1.6.1</version>
    </dependency>

    <dependency>
       <groupId>jaxen</groupId>
       <artifactId>jaxen</artifactId>
       <version>1.1.6</version>
    </dependency>
SpringSimulation.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans>
<!--     设置JavaBean 对应的 bean 标签-->
     <bean id="userInfo" class="Simulation.UserInfo"></bean>
     <bean id="userService" class="Simulation.UserService"></bean>
</beans>

//UserInfo.java
package Simulation;
/**
 * @author Vodka
 * @date 2021/11//19:03
 */
public class UserInfo 
    private  String Name;
    private  int Age;
    private  int Gender;

    public UserInfo(String name, int age, int gender) 
        Name = name;
        Age = age;
        Gender = gender;
    

    public UserInfo() 
    

    public void test()
        System.out.println("UserInfoTest");
    

    @Override
    public String toString() 
        return "UserInfo" +
                "Name='" + Name + '\\'' +
                ", Age=" + Age +
                ", Gender=" + Gender +
                '';
    

    public String getName() 
        return Name;
    

    public void setName(String name) 
        Name = name;
    

    public int getAge() 
        return Age;
    

    public void setAge(int age) 
        Age = age;
    

    public int getGender() 
        return Gender;
    

    public void setGender(int gender) 
        Gender = gender;
    




//UserService.java
package Simulation;

/**
 * @author Vodka
 * @date 2021/11//19:29
 */
public class UserService 
    private  String Quality;

    public void test()
        System.out.println("UserServiceTest");
    
    @Override
    public String toString() 
        return "UserService" +
                "Quality='" + Quality + '\\'' +
                '';
    

    public UserService() 
    

    public String getQuality() 
        return Quality;
    

    public void setQuality(String quality) 
        Quality = quality;
    

    public UserService(String quality) 
        Quality = quality;
    


//BeanSimulation.java(Interface)
package Simulation;

/**
 * @author Vodka
 * @date 2021/11//18:56
 */

//定义获取Bean对象的接口
public interface BeanSimulation 
    //   重写GetBean()方法
    Object GetBean(String ID);




//MyBean.java
package Simulation;
/**
 * @author Vodka
 * @date 2021/11//16:58
 * @descreption Bean属性对象,用来存放配置文件中bean标签对应的Id和class属性值
 */
public class MyBean 
    private  String ID;  //Bean对象的Id
    private  String Clazz;   //Bean 相应类的完整路径名

    @Override
    public String toString() 
        return "MyBeanTest" +
                "ID='" + ID + '\\'' +
                ", Clazz='" + Clazz + '\\'' +
                '';
    

    public void setID(String ID) 
        this.ID = ID;
    

    public void setClazz(String clazz) 
        Clazz = clazz;
    

    public String getID() 
        return ID;
    

    public String getClazz() 
        return Clazz;
    

    public MyBean(String ID, String clazz) 
        this.ID = ID;
        Clazz = clazz;
    








//MyFactory.java
package Simulation;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Vodka
 * @date 2021/11//18:41
 *
 */

/*
   1.使用dom4j 解析含有Bean对象id和路径信息的XML文件,存储到List集合,每个元素代表一个bean的信息。
   2.遍历List集合,通过反射(Class.forName(class).newinstance())得到对应的实例化对象,存储到Map对象中
   3.通过ID获取相应的实例对象
*/


public class MyClassPathXMLApplicationContext implements BeanSimulation
    private List<MyBean> BeansInfoList =  null;      //存放从配置文件中获取到的bean标签信息
    private Map<String,Object> BeanMap = new HashMap<>();  //存放已经实例化好的对象,可直接通过id获取对应的对象
//    通过构造器获取配置文件信息
    public MyClassPathXMLApplicationContext(String FileName)
//        通过dom4j 解析配置文件,得到List集合
         this.parseXml(FileName);
//        通过反射得到对应的实例化对象
         this.instanceBean();
    


   /*
   *   通过dom4j 解析配置文件,得到List集合
   *    1.获取解析器
   *    2.获取配置文件的URL,通过解析器解析配置文件
   *    3.通过xpatj 语法解析,获取beans标签下的所有bean标签,返回元素集合
   *    4.判断元素集合是否为空,不为空,遍历集合
   *    5.获取bean标签元素的属性  (id 和 class 属性值),接着获取MyBean对象,将id和class属性值设置到对象中,
   *      再将对象设置到MyBean集合。
   * */
    private void parseXml(String fileName) 
        SAXReader  saxReader = new SAXReader();   //获取解析器
        URL url = this.getClass().getClassLoader().getResource(fileName);  //获取XML配置文件的URL
        try
            Document document = saxReader.read(url);
            XPath xPath = document.createXPath("beans/bean");    //通过xparse语法解析,获取beans下面所有bean标签
            List<Element> elementList = xPath.selectNodes(document); //解析文档对象,返回集合
            if(elementList != null && !elementList.isEmpty())
                BeansInfoList = new ArrayList<>();
                for( Element item : elementList)
//                    获取bean标签元素的属性(id和class属性)
                    String ID = item.attributeValue("id");
                    String Clazz = item.attributeValue("class");
//                    获取MyBean对象,再将Bean对象设置到相应Map集合中
                    MyBean myBean = new MyBean(ID,Clazz);
                    BeansInfoList.add(myBean);
                
            
        catch(Exception e)
             e.printStackTrace();
        
    
  /*
  *   通过反射得到对应的实例化对象,放置在Map对象
  *    1.判断对象是否为空,若不为空,则遍历BeansInfoList , 获取对象的id 和 class 属性
  *    2.通过类的全路径名,反射得到实例化对象: Class.forName(class).newInstance()
  *    3.再将相应的id 和 实例化对象设置到 Map 结合中
  * */
    private void instanceBean() 
        if(BeansInfoList != null && !BeansInfoList.isEmpty())
            System.out.println(BeansInfoList);
            for(MyBean bean : BeansInfoList)
                try 
                  Object obj =  Class.forName(bean.getClazz()).getConstructor().newInstance();
                  BeanMap.put(bean.getID(),obj);
                 catch (Exception e) 
                    e.printStackTrace();
                
            
        
    
    //   重写GetBean()方法
    @Override
    public Object GetBean(String ID) 
         return BeanMap.get(ID);
    





//App.java
package com.vodka;

import Simulation.MyClassPathXMLApplicationContext;
import Simulation.UserInfo;
import Simulation.UserService;

/**
 * Hello world!
 *
 */
public class App

    public static void main( String[] args )
    
//        得到实例化工厂对象
       MyClassPathXMLApplicationContext MyFactory = new MyClassPathXMLApplicationContext("SpringSimulation.xml");
       UserInfo UI = (UserInfo) MyFactory.GetBean("userInfo");
       UserService US = (UserService) MyFactory.GetBean("userService");

       UI.test();
       US.test();
    


三.Spring IOC 核心技术:
-工厂设计模式(简单工厂,工厂方法,抽象工厂)
-XML解析 (Dom4j)
-反射技术(实例化对象,反射获取方法,反射获取属性,反射获取构造器,反射调用方法)
-策略模式 (加载资源,加载不同的类资源时,加载类里的定义了获取实例化对象的所有方法,只需提供不同的类ID,加 载就可以提供不同 的实例化对象)
-单例(IOC 创建可以实例化对象的对象)

四. 多配置文件加载:

<?xml version="1.0" encoding="utf-8"?>
<beans>
    <import resource="One.xml"></import>
    <import resource="SpringSimulation.xml"></import>
</beans>

以上是关于Spring IOC的主要内容,如果未能解决你的问题,请参考以下文章

Spring IOC下的工厂模式

[Spring5]IOC容器_Bean管理_工厂Bean

Spring IOC&DI

Spring的IOC分析

Spring之IOC

Java Spring-IOC和DI