IOC[inversion Of Control 反转控制](下)

简介: IOC[inversion Of Control 反转控制](下)

通过静态工厂获取对象


package com.spring.factory;
import com.spring.beans.Monster;
import java.util.HashMap;
import java.util.Map;
public class MyStaticFactory {
    private static Map<String, Monster> monsterMap;
    static {
        monsterMap = new HashMap<String, Monster>();
            monsterMap.put("monster_01", new Monster(100, "黄袍怪", "一阳指"));
        monsterMap.put("monster_02", new Monster(200, "九头金雕", "如来神掌"));
    }
    public static Monster getMonster(String key) {
      return monsterMap.get(key);
    }
}


<!-- 通过静态工厂来获取bean 对象-->
<bean id="my_monster" class="com.spring.factory.MyStaticFactory" factory-method="getMonster">
<!-- constructor-arg 标签提供key -->
<constructor-arg value="monster_01"/>
</bean>


通过实例工厂获取对象


package com.spring.factory;
import com.spring.beans.Monster;
import java.util.HashMap;
import java.util.Map;
public class MyInstanceFactory {
        private Map<String, Monster> monster_map;
        //非静态代码块
        {
            monster_map = new HashMap<String, Monster>();
            monster_map.put("monster_01", new Monster(100, "猴子精", "吃桃"));
            monster_map.put("monster_02", new Monster(200, "佛祖", "如来神掌"));
        }
        public Monster getMonster(String key) {
            return monster_map.get(key);
        }
}


<bean id="myInstanceFactory" class="com.spring.factory.MyInstanceFactory"/>
<bean id="my_monster2" factory-bean="myInstanceFactory"
factory-method="getMonster">
  <constructor-arg value="monster_02"/>
</bean>


bean 配置信息重用(继承)


在spring 的ioc 容器, 提供了一种继承的方式来实现bean 配置信息的重用。

<!-- 继承的方式来实现bean 配置信息的重用-->
<bean id="monster10" class="com.spring.beans.Monster">
    <property name="monsterId" value="10"/>
    <property name="name" value="蜈蚣精"/>
    <property name="skill" value="蜇人"/>
</bean>
<!-- parent="monster10" 就是继承使用了monster10 的配置信息-->
<bean id="monster11" class="com.spring.beans.Monster"
parent="monster10"/>
<!-- 当我们把某个bean设置为abstract="true" 这个bean只能被继承,而不能实例化了-->
<bean id="monster12" class="com.spring.beans.Monster" abstract="true">
        <property name="monsterId" value="12"/>
        <property name="name" value="美女蛇"/>
        <property name="skill" value="诱惑"/>
</bean>
<!-- parent="monster12" 就是继承使用了monster12 的配置信息-->
<bean id="monster13" class="com.spring.beans.Monster"
parent="monster12"/>


测试

@Test
public void getBeanByExtends() {
    ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
    Monster monster1 = ioc.getBean("monster11", Monster.class);
    System.out.println(monster1);
    Monster monster2 = (Monster) ioc.getBean("monster13", Monster.class);
    System.out.println(monster2);
}


bean 创建顺序


  1. 在spring 的ioc 容器, 默认是按照配置的顺序创建bean 对象
<bean id="student01" class="com.bean.Student" />
<bean id="department01" class="com.bean.Department" />

会先创建student01 这个bean 对象,然后创建department01 这个bean 对象。


  1. 如果这样配置
<bean id="student01" class="com.bean.Student" depends-on="department01"/>
<bean id="department01" class="com.bean.Department" />

会先创建department01 对象,再创建student01 对象.


bean 对象的单例和多例


在spring 的ioc 容器, 在默认是按照单例创建的,即配置一个bean 对象后,ioc 容器只会创建一个bean 实例。

如果我们希望ioc容器配置某个bean 对象,以多个实例形式创建,则可以通过配置scope=“prototype” 来指定。

//配置beans.xml
<bean name="car" scope="prototype" class="com.spring.beans.Car"/>


测试

@Test
public void getBeanByPrototype() {
  ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
  for (int i = 0; i < 3; i++) {
      Car car = ioc.getBean("car", Car.class);
      System.out.println(car);
  }
}


注意
1. 默认是单例singleton, 在启动容器时, 默认就会创建, 并放入到singletonObjects 集合。
2. 当<bean scope="prototype" > 设置为多实例机制后, 该bean 是在getBean()时才创建。
3. 如果是单例singleton, 同时希望在getBean 时才创建, 可以指定懒加载
lazy-init="true"。
4. 通常情况下, lazy-init 使用默认值false , 在开发看来用空间换时间是值得的, 除非有特殊的要求。
5. 如果scope="prototype" 多实例机制,lazy-init 属性的值不管是ture, 还是false 都是在getBean 时候创建对象。


bean 的生命周期


bean 对象创建是由JVM 完成的。通过如下步骤可以进行测试


  1. 1.执行构造器。
  2. 2.执行set 相关方法。
package com.spring.beans;
public class House {
    private String name;
    public House() {
      System.out.println("House() 构造器");
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
      System.out.println("House setName()...");
      this.name = name;
    }
    public void init() {
      System.out.println("House init()..");
    }
    public void destory() {
      System.out.println("House destory()..");
    }
}


3.调用bean 的初始化的方法(需要配置)。

<!-- 配置bean 的初始化方法和销毁方法-->
<bean id="house" class="com.spring.beans.House"
    init-method="init"
    destroy-method="destory">
    <property name="name" value="深圳"/>
</bean>


  1. 4.使用bean。
  2. 5.当容器关闭时候,调用bean 的销毁方法(需要配置)。
    测试
@Test
public void beanLife() {
    ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
    House house = ioc.getBean("house", House.class);
    System.out.println(house);
    ((ConfigurableApplicationContext) ioc).close();
}


注意


  1. 1.初始化init 方法和destory 方法, 由程序员设置。
  2. 2.销毁方法当关闭容器时,才会被调用。


配置bean 的后置处理器


  1. 在spring 的ioc 容器,可以配置bean 的后置处理器。
  2. 该处理器/对象会在bean 初始化方法调用前和初始化方法调用后被调用。
  3. 程序员可以在后置处理器中编写自己的代码。
public class MyBeanPostProcessor implements BeanPostProcessor {
    /**
    * 在bean 初始化之前完成某些任务
    * @param bean : 就是ioc 容器返回的bean 对象, 如果这里被替换会修改,则返
    回的bean 对象也会被修改
    * @param beanName: 就是ioc 容器配置的bean 的名称
    * @return Object: 就是返回的bean 对象
    */
    public Object postProcessBeforeInitialization(Object bean, String beanName)
    throws BeansException {
        // TODO Auto-generated method stub
        System.out.println("postProcessBeforeInitialization 被调用" + beanName + "
        bean= " + bean.getClass());
                           return bean;
    }
    /**
    * 在bean 初始化之后完成某些任务
    * @param bean : 就是ioc 容器返回的bean 对象, 如果这里被替换会修改,则返
    回的bean 对象也会被修改
    * @param beanName: 就是ioc 容器配置的bean 的名称
    * @return Object: 就是返回的bean 对象
    */
    public Object postProcessAfterInitialization(Object bean, String beanName)
    throws BeansException {
        System.out.println("postProcessAfterInitialization 被调用" + beanName + " bean= "
        + bean.getClass());
        return bean;
    }
}


配置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
    http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置bean 的初始化方法和销毁方法-->
<bean id="house" class="com.spring.beans.House"
init-method="init"
destroy-method="destory">
  <property name="name" value="北京豪宅"/>
</bean>
<!-- bean 后置处理器的配置-->
<bean id="myBeanPostProcessor"
class="com.spring.beans.MyBeanPostProcessor" />
</beans>


测试

@Test
public void testBeanPostProcessor() {
    ApplicationContext ioc = new ClassPathXmlApplicationContext("beans02.xml");
    House house = ioc.getBean("house", House.class);
    System.out.println(house);
    //关闭容器
    ((ConfigurableApplicationContext) ioc).close();
}

使用AOP(反射+动态代理+IO+容器+注解)执行后置处理器,可以对IOC 容器中所有的对象进行统一处理,比如日志处理/权限的校验/安全的验证/事务管理。是切面编程的特点。


通过属性文件给bean 注入值


<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"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    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.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
<!--
    1. 通过属性文件给bean 注入值,
    2. 需要导入: xmlns:context 名字空间,并指定属性文件路径
-->
<context:property-placeholder location="classpath:my.properties"/>
<bean id="monster10" class="com.spring.beans.Monster">
    <property name="monsterId" value="${id}"/>
    <property name="name" value="${name}"/>
    <property name="skill" value="${skill}"/>
</bean>


相关文章
|
JSON API 数据格式
商品详情数据JSON格式示例参考(api接口)
JSON数据格式的商品详情数据通常包含商品的多个层级信息,以下是一个综合多个来源信息的JSON数据格式的商品详情数据示例参考:
convmv命令对文件名进行编码转换
convmv命令对文件名进行编码转换
316 0
|
监控 搜索推荐 定位技术
阿里云推送移动推送
阿里云推送是阿里巴巴集团旗下的一款云端消息推送服务。作为云计算领域的领军企业之一,阿里云通过推送技术为开发者和企业提供了高效、可靠的消息传递服务,帮助他们快速将消息推送给设备或用户,实现实时通知和消息交互。
|
监控 测试技术 Shell
性能测试 基于Python结合InfluxDB及Grafana图表实时监控Android系统和应用进程
性能测试 基于Python结合InfluxDB及Grafana图表实时监控Android系统和应用进程
550 0
性能测试 基于Python结合InfluxDB及Grafana图表实时监控Android系统和应用进程
Google Earth Engine(GEE)——export影像导出错误Error: Image.clipToBoundsAndScale, argument ‘input‘: Invalid
Google Earth Engine(GEE)——export影像导出错误Error: Image.clipToBoundsAndScale, argument ‘input‘: Invalid
828 0
Google Earth Engine(GEE)——export影像导出错误Error: Image.clipToBoundsAndScale, argument ‘input‘: Invalid
|
前端开发 JavaScript IDE
千姿百态,瞬息万变,Win11系统NeoVim打造全能/全栈编辑器(前端/Css/Js/Vue/Golang/Ruby/ChatGpt)
我曾经多次向人推荐Vim,其热情程度有些类似现在卖保险的,有的时候,人们会因为一些弥足珍贵的美好暗暗渴望一个巨大的负面,比如因为想重温手动挡的快乐而渴望买下一辆二十万公里的老爷车,比如因为所谓完美的音质而舍不得一个老旧的有线耳机,比如因为一个铜炉火锅而期待北京那漫长而寒冷的冬天。
千姿百态,瞬息万变,Win11系统NeoVim打造全能/全栈编辑器(前端/Css/Js/Vue/Golang/Ruby/ChatGpt)
|
弹性计算
使用ECS服务器
我是一名学习计算机专业的学生,目前大三。因为平时学习的原因,需要用到云服务器来部署自己开发的项目进行测试,便在网上寻找了多家云服务器,最终找到了阿里云这个平台。在学校的介绍下,又了解到“飞天加速计划·高校学生在家实践”活动,便抱着试一试的心态领取了两周。
105 0
|
Web App开发 JavaScript 开发工具
|
测试技术 C++
那些年,我们一起找过的工作
        最近和学弟吃饭,听见他们谈论有关实习和找工作的话题。作为一个过来人,我参加过很多公司的笔试和面试。我觉得自己有义务将自己的经历和大家分享,为大家找工作提供参考。
1617 0