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>


相关文章
|
2月前
|
设计模式 Java Maven
Spring Aop 底层责任链思路实现-springaopdi-ceng-ze-ren-lian-si-lu-shi-xian
Spring Aop 底层责任链思路实现-springaopdi-ceng-ze-ren-lian-si-lu-shi-xian
37 1
|
9月前
|
Java 应用服务中间件 Spring
Spring框架(《面向切面》——对象值的注入——输出) 1
Spring框架(《面向切面》——对象值的注入——输出)
Spring框架(《面向切面》——对象值的注入——输出) 1
|
7月前
|
机器学习/深度学习 算法 测试技术
C++前缀和算法的应用:DI序列的有效排列的原理、源码及测试用例
C++前缀和算法的应用:DI序列的有效排列的原理、源码及测试用例
|
9月前
|
XML Java 程序员
IOC[inversion Of Control 反转控制](上)
IOC[inversion Of Control 反转控制](上)
38 0
|
9月前
|
Java 数据库 Spring
Spring框架(《面向切面》——对象值的注入——输出) 2
Spring框架(《面向切面》——对象值的注入——输出)
|
9月前
|
存储 C++ 容器
6.1 C++ STL 序列映射容器
Map/Multimap 映射容器属于关联容器,它的每个键对应着每个值,容器的数据结构同样采用红黑树进行管理,插入的键不允许重复,但值是可以重复的,如果使用`Multimap`声明映射容器,则同样可以插入相同的键值。
62 0
|
9月前
|
XML Java 数据格式
一文讲透Spring的IOC反转控制
一文讲透Spring的IOC反转控制
65 0
|
10月前
|
SQL 设计模式 开发框架
Spring的反转控制你真的明白了吗?(下)
Spring的反转控制你真的明白了吗?
|
10月前
|
XML 设计模式 安全
Spring的反转控制你真的明白了吗?(上)
Spring的反转控制你真的明白了吗?
|
10月前
|
Java 测试技术 容器
一篇文章解释清楚IOC和DI
一篇文章解释清楚IOC和DI