ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring:IOC原理

2021-10-24 23:03:15  阅读:127  来源: 互联网

标签:容器 配置文件 service 对象 Spring 创建对象 bean 原理 IOC


目录

程序的耦合和解耦

传统的MVC模式

使用工厂模式进行解耦

Spring IOC原理

 Spring的IOC解决方法

简单搭建spring-maven环境

获取容器的方法

bean标签

实例化Bean的三种方式

依赖注入

构造方法注入

set注入

注入集合


Spring是全栈轻量级开源框架,它的核心是AOP、IOC.

 

程序的耦合和解耦

传统的MVC模式

逻辑层依赖于持久层;表现层依赖于逻辑层,所以这种耦合程度太高了

还存在编译期报错的情况,因为对象全是new出来的。编译期异常:当没有导入该jar包时就会报出该异常。

使用工厂模式进行解耦

思路:

  • 使用配置文件存放全限定类名,使用properties进行存储(key-value),通过key值获取全限定类名,(key相当于spring配置文件中的id,value相当于spring配置文件中的class)
  • 使用得到的全限定类名通过反射创建对象(反射机制:动态创建对象,不会出现编译期异常,例如:删除了daoimpl 文件 也不会报出编译异常,只会报出运行时异常
  • 将key和创建的对象存储到一个map中(容器的概念,ioc容器的底层其实也是一个map),实现了单例的效果,容器创建的同时,对象已经创建好了。后面,调用方法就可以从容器中取出对象了
/**
 * JavaBean工厂类 读取配置文件,通过读取到的全限定类名创建对象,并且将其存储到map中
 */
public class  beanfactory {
    private static Properties properties;
    private static Map beans;
    static {
        try {
            beans=new HashMap<String,Object>();
            properties=new Properties();
            InputStream asStream = beanfactory.class.getClassLoader().getResourceAsStream("bean.properties");
            properties.load(asStream);
            Enumeration<Object> keys = properties.keys();
            while (keys.hasMoreElements()){
                String key=keys.nextElement().toString();
                Object object=Class.forName(properties.getProperty(key)).newInstance();
                beans.put(key,object);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }

    }
    public static Object getBean(String className){
        return beans.get(className);
    }
}

/**
 * service的实现类
 * 通过使用JavaBean工厂类进行解耦
 */
public class serviceimpl implements Iservice {
Idao idao=(daoimpl)beanfactory.getBean("daoimpl");
    @Override
    public void Sadd() {
        idao.add();
    }
}
/**
 * web层 创建serviceimpl对象的方法 与上方相同
 */

Spring IOC原理

将JavaBean对象的控制权交给工厂,实现了控制反转

 Spring的IOC解决方法

简单搭建spring-maven环境

Maven工厂导入坐标

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>

编写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">
   <bean id="service" class="dome1.service.impl.serviceimpl"></bean>
</beans>

测试代码

 public static void main(String[] args) {
        //获取容器对象
       ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
       //从容器中取走对象
       serviceimpl service = (serviceimpl) context.getBean("service");
        System.out.println(service);//dome1.service.impl.serviceimpl@7d9d1a19
    }

获取容器的方法

  • ClassPathXmlApplicationContext   从项目根路径下获取配置文件
  • FileSystemXmlApplicationContext  从磁盘路径上加载配置文件
  • AnnotationConfigApplicationContext  读取注解创建容器对象

ApplicationContext与BeanFactory的区别

BeanFactory是Spring容器的顶层接口,创建对象的时机:什么时候使用什么时候创建对象(适合多例)

ApplicationContext:创建对象的时机是只要读取配置文件,就创建对象(适合单例对象)

public static void main(String[] args) {
        //单例对象
        ApplicationContext context1 = new ClassPathXmlApplicationContext("bean.xml");
        Object service = context1.getBean("service");
        //多例对象
        ClassPathResource resource = new ClassPathResource("bean.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);
        Object service1 = beanFactory.getBean("service");
    }

bean标签

属性

  • id:唯一标识,用于获取对象
  • class:指定全限定类名,用于反射创建对象
  • scope:指定对象的作用域
    • singleton:单例(默认值)
    • prototype:多例的
    • request:web项目中,spring创建一个javabean对象,将对象存入request域中
    • session:web项目中,spring创建一个javabean对象,将对象存入session域中
    • global session :应用在集群中

有关生命周期的属性

  • init-method:初始化方法
  • destroy-method:销毁方法

示例代码:bean的生命周期

bean配置

 <bean id="service" class="dome1.service.impl.serviceimpl" init-method="init" destroy-method="display">

测试代码

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        Object service = context.getBean("service");
        context.close();//手动关掉容器
    }

控制台输出

 单例对象:与容器相关,创建容器的同时对象就会被创建,销毁容器时对象就会被销毁。

多例对象:当使用对象时才会被创建,只要对象在使用,就一直活着;当对象长时间不用时,就会被java的垃圾回收器回收了

实例化Bean的三种方式

  • 使用无参构造(默认):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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--   无参构造-->
   <bean id="dome1" class="dome1.service1.dome1"/>
<!--   实例工厂(两步):先将工厂对象放进spring 在从方法中获取对象-->
   <bean id="dome2" class="dome1.service1.dome2"/>
   <bean id="dome21" factory-bean="dome2" factory-method="getDome1"/>
<!--   静态工厂 直接调用方法获取对象-->
   <bean id="dome3" class="dome1.service1.dome3" factory-method="getDome"/>
</beans>

依赖注入

构造方法注入

bean标签内使用constructor标签

属性

  • name:构造方法的形参名称
  • type:构造方法的形参类型(该类型在形参列表中只能使用一次)
  • index:构造方法的形参列表的索引
  • value:给基本类型和string赋值
  • ref:赋的值是bean类型(前提必须在配置文件中配置过)

优点:在获取bean对象时,注入数据是必须的操作,否则无法创建成功

缺点:如果用不到这些数据也必须创建

set注入

bean标签内使用property标签

属性

  • name:类的属性名(set方法名 后面的部分)
  • ref:给属性赋值是其他的bean类型
  • value:给基本类型和string赋值

优点:创建对象时没有明确的限制,可以直接使用默认构造方法

缺点:如果要求某个变量必须有值,这种方法无法保证必须有值,例如:没有调用set方法等等

<!--   有参构造 构造方法的注入-->
   <bean id="now" class="java.util.Date"/>
   <bean id="dome11" class="dome1.service1.dome1">
      <constructor-arg name="string" value="张三"/>
      <constructor-arg type="java.lang.Integer" value="123"/>
      <constructor-arg index="2" ref="now"/>
   </bean>
<!--   set注入-->
   <bean id="dome12" class="dome1.service1.dome1">
      <property name="string" value="李四"/>
      <property name="date" ref="now"/>
      <property name="integer" value="12"/>
   </bean>

注入集合

本质:就是set注入

用于给list结构注入的标签:list、set、array

用于给map结构注入的标签:map、props

同一结构的标签可以互换

<!--   注入集合-->
   <bean id="dome4" class="dome1.service1.dome4">
<!--      数组-->
      <property name="strings">
         <array>
            <value>AAA</value>
            <value>BBB</value>
         </array>
      </property>
<!--      list-->
      <property name="list">
         <list>
            <value>CCC</value>
            <value>SSS</value>
         </list>
      </property>
<!--      set-->
      <property name="set">
         <set>
            <value>WWW</value>
            <value>AAA</value>
         </set>
      </property>
<!--      map-->
      <property name="map">
         <map>
            <entry key="AAA" value="BBBB"/>
            <entry key="BBB" value="CCC"/>
         </map>
      </property>
<!--      pro-->
      <property name="properties">
         <props>
            <prop key="AAA">BBB</prop>
            <prop key="WWW">CCC</prop>
         </props>
      </property>
   </bean>

标签:容器,配置文件,service,对象,Spring,创建对象,bean,原理,IOC
来源: https://blog.csdn.net/qq_51476114/article/details/120934157

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有