必威网站一半夜间想的查漏补缺 , Spring 中 Bean 之间的仗问题。六、容器中Bean的生命周期。

老是扣开还见面发现自己的欠缺 .

仰关系注入下的行:

Spring提供简单种植艺术在Bean的满贯性质设置成后实行一定的表现:

  • 使用init-method属性。
  • 实现InitializingBean接口。
    首先种植办法:使用init-method属性指定某个方法在Bean全部因关系设置结束后活动执行。使用这种方法不欲开口代码和Spring的接口耦合在一起,代码污染小。
    老二种植方法:让Bean类实现initlializingBean接口,该接口提供一个主意void
    afterPropertiesSet() thorows
    Exception;Spring会在吗该Bean注入依赖关系之后,调用该Bean所实现的afterPropertiesSet()方法。

Chinese.java

package entity;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import inter.Axe;
import inter.Persion;

public class Chinese implements Persion,InitializingBean,BeanNameAware,ApplicationContextAware {

    private Axe axe;
    @Override
    public void setApplicationContext(ApplicationContext arg0)
            throws BeansException {
        System.out.println("======setApplicationContext=======");

    }

    public Chinese()
    {
        System.out.println("Spring实例化主调Bean:Chinese实例...");
    }
    @Override
    public void setBeanName(String arg0) {
        // TODO Auto-generated method stub
        System.out.println("=============setBeanName===============");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // TODO Auto-generated method stub
        System.out.println("正在执行初始化方法afterPropertiesSet.....");
    }

    @Override
    public void useAxe() {
        // TODO Auto-generated method stub
        System.out.println(axe.chop());
    }
    public void setAxe(Axe axe)
    {
        System.out.println("Spring调用setAxe()执行依赖注入...");
        this.axe=axe;
    }

    public void init()
    {
        System.out.println("正在执行初始化方法init....");
    }
}

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"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd" >
     <bean id="steelAxe" class="entity.SteelAxe"/>

     <!-- 配置ChineseBean,使用init-method="init" -->
     <bean id="chinese" class="entity.Chinese" init-method="init">
        <property name="axe" ref="steelAxe" />
     </bean>
</beans>

输出

Spring实例化主调Bean:Chinese实例...
Spring调用setAxe()执行依赖注入...
=============setBeanName===============
======setApplicationContext=======
正在执行初始化方法afterPropertiesSet.....
正在执行初始化方法init....
钢斧砍柴真快!

只要有类实现了Initializing接口,当该Bean所有的乘关系为装完成后,Spring容器会活动调用该Bean实例的setPropertiesSet()方法;其尽结果与应用init-method属性指定生命周期一样。但具体Initializing接口污染代码,是低侵入式设计。

      当一个 singten 的 Bean 依赖一个 prototype 的 Bean 时 ,
如果不加注意 , 会发生局部竟之事体 , prototype 变为了 singten 了 ,
这是为什么呢 ?

      这是 Spring 容器本身的特性 , 当初始化 Spring 容器时 ,
容器会预初始化容器被具备的 singleton 的 Bean , 由于 singleton Bean
依赖让 propertype Bean , 因此 , 容器在初始化 singleton Bean
之前会预先创造 propertype Bean , 然后以创造好之 propertype Bean
作为性能注入到 singleton Bean 中 , 一旦容器创建好 singleton Bean ,
容器在她销毁之前都不会为它第二潮注入 propertype Bean , 这样一来 ,
propertype Bean 却展现有了 singleton 的表现了 , 与设计的初衷背道而驰 .

Bean销毁之前的一言一行:

Spring提供了少种植定制Bean实例销毁之前的特定行为:

  • 使用destroy-method属性。
  • 实现DisposableBean接口。
    率先种植艺术:使用destroy-method属性指定某个方法以Bean销毁之前自动为执行,使用这种办法不欲用代码和Spring的接口耦合在一起,代码污染小。
    仲栽艺术:让Bean类实现DisposableBean接口,实现该接口提供的方式void
    destroy() throws Exception。

布文件以及实例化之后的beans.xml文件类。

釜底抽薪是题目发一定量种方式 :

协调作用域不联合的Bean:

当singleton作用域的Bean依赖让prototype作用域的Bean时,会有不齐的场面,解决拖欠问题发生星星点点栽思路:

  • 放弃依赖注入:singleton作用域的Bean每次用prototype作用域的Bean时,主动向容器请求新的Bean实例,即可保证每次注入的prototype
    Bean实例都是流行的实例。
  • 动方式注入:方法注入通常以lookup方法注入。

为利用lookup方法注入,大致需要少步

  • 以调用者Bean的兑现类似定义为抽象类,并定义一个华而不实方法来抱给依的Bean。
  • 于<bean…/>元素被补充加<lookup-method…/>子元素让Spring为调用者Bean的贯彻类似实现指定的纸上谈兵方法。

Chinese.java

public abstract class Chinese implements Persion
{
     private Dog dog;
     //定义抽象方法,该方法用于获取被依赖的Bean
     public abstract Dog getDog();
     public void hunt()
     {
           System.out.println("我带着"+getDog()+"出去打猎");
           System.out.println(getDog().run());
     }
}

采用<lookup-method…/>元素用指定如下两个特性:

  • name:指定要让Spring实现的方。
  • bean:指定Spring实现该方法的回来值。

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"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd" >


     <bean id="chinese" class="entity.Chinese">
       <!-- Spring只要检测到lookup-method元素,Spring会自动为该元素的name属性所指定的方法提供实现体 -->
        <lookup-method name="getDog" bean="gunDog"/>
     </bean>

     <!-- 指定gunDog Bean的作用域为prototype,希望程序每次使用该Bean时都得到不同的实例 -->
     <bean id="gunDog" class="entity.GunDog" scope="prototype">
        <property name="name" value="旺财"/>
     </bean>
</beans>

Spring会采用运行时动态增长的点子来落实<lookup-method…/>元素所指定的泛方法,如果目标抽象类(如齐Chinese类)实现了接口,Spring会采用JDK动态代理来实现该抽象类,并也底实现抽象方法;如果抽象类没有实现了接口,Spring会采用cglib实现该抽象类,并为的实现抽象方法。

  • 放弃依赖注入 : singleton 作用域的 Bean 每次都需要 propertype
    作用域的 Bean 时, 主动为容器请求新的 Bean 实例 ,
    即可保证每次注入的 Bean , 都是初的 propertype Bean 的实例 . (
    不推荐 )
  • 利用方式注入 : 使用 <lookup-method>
    标签指定一个空洞方法与 propertype Bean . 具体落实即是拿 singleton
    Bean 的近乎声明也一个浮泛类 , 并提供一个虚幻方法 ,
    这个抽象方法就是是用来注入 propertype Bean 的 . ( 推荐用 )

脚举一个板栗 :

       一个猎人 , 有田的功能 , 每次打猎都带齐猎狗 ,
但是历次带的猎狗都不同 , 也就是是顺应地方的一个是 singten , 一个凡是
prototype , 猎人依赖猎狗 .

 

1

注 : 利用方式注入的真相使用了代理 , 分为简单种植代理 , JDK 代理及
cglib 代理 , 如果目标抽象类实现了接口 , Spring 容器会采取 JDK
代理实现抽象方法 , 如果目标类没有落实了接口 , Spring 会采用 cglib 代理
, 实现该抽象方法 .

相关文章