在IoC容器中装配Bean

      Spring容器启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表,然后根据这张注册表实例化Bean,装配好Bean之间的依赖关系,为上层应用提供准备就绪的运行环境。

      Bean配置信息时Bean的元数据信息,它由一下4个方面组成:

      1. Bean的实现类;

      2. Bean的属性信息,如数据源的连接数,用户名;

      3. Bean的依赖关系,Spring根据依赖关系配置完成Bean之间的装配;

      4. Bean的行为配置,如生命周期及个过程的回调函数等。

      Bean元数据信息在Spring容器中的内部对应物是由一个个BeanDefinition形成的Bean注册表,Spring实现了Bean元数据信息内部和外部表示的解耦。

      Bean配置信息定义了Bean的实现和依赖关系,Spring容器根据各种形式的Bean配置信息在容器内部建立Bean定义注册表,然后根据注册表加载、实例化Bean,并建立Bean和Bean的依赖关系,最后将这些就绪的Bean放到Bean缓冲池中,以供外层的应用程序进行调用。

 

一、依赖注入

     1. 属性注入

     a. 属性注入即通过setXxx()方法注入Bean的属性值或依赖对象,属性注入方式具有可选择性和灵活性高的优点。

     b. 属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。

     c. Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法。

package spring.ioc.demo1;

public class Car {

    private String brand;

    private String color;

    private int maxSpeed;

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getMaxSpeed() {
        return maxSpeed;
    }

    public void setMaxSpeed(int maxSpeed) {
        this.maxSpeed = maxSpeed;
    }
    
    public String toString(){
        return "the car is:"+ getBrand() + ", color is:" +getColor() +", maxspeed is:"+getMaxSpeed();
    }

    public Car() {

    }

    public Car(String brand, String color, int maxSpeed) {
        this.brand = brand;
        this.color = color;
        this.maxSpeed = maxSpeed;
    }

    public void introduce() {
        System.out.println("brand:" + brand + ";color:" + color + ";maxSpeed:"
                + maxSpeed);
    }

}
<bean id="car1" class="spring.ioc.demo1.Car"
     <property name="brand"><value>spring注入-红旗001</value></property>
     <property name="color"><value>spring注入-紫色</value></property>
     <property name="maxSpeed"><value>520</value></property>
</bean>

     

     2.构造函数注入

     a. 它保证一些必要的属性在Bean实例化时就得到设置,它保证Bean实例化以后就可以使用;

     b. Bean必须提供带参的构造函数。

public class Car{

.......

public Car(String brand, String color, int maxSpeed) {
        this.brand = brand;
        this.color = color;
        this.maxSpeed = maxSpeed;
    }

.......

}
<bean id="car1" class="spring.ioc.demo1.Car"
     <construcotr-arg type="java.lang.String"><value>spring注入-红旗001</value></construcotr-arg>
     <construcotr-arg type="java.lang.String"><value>spring注入-紫色</value></construcotr-arg>
     <construcotr-arg type="double"><value>520</value></construcotr-arg>
</bean>

      也可以通过索引的方式进行配置:

<bean id="car1" class="spring.ioc.demo1.Car"
     <construcotr-arg index="0"><value>spring注入-红旗001</value></construcotr-arg>
     <construcotr-arg index="1"><value>spring注入-紫色</value></construcotr-arg>
     <construcotr-arg index="2"><value>520</value></construcotr-arg>
</bean>

      但是为了避免潜在的配置歧义,例如Bean存在多个构造函数,我们最好还是设置一下参数的Type.

      3. 引用其他Bean

package spring.ioc.iocbean;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import spring.ioc.demo1.Car;

public class Boss {
    
    private List<String> favorites = new ArrayList<String>();
    
    private Car car;
    
    private Map<String, Car> jobs = new HashMap<String, Car>();
    
    private Properties mails = new Properties();
    
    public Properties getMails() {
        return mails;
    }

    public void setMails(Properties mails) {
        this.mails = mails;
    }

    public Map<String, Car> getJobs() {
        return jobs;
    }

    public void setJobs(Map<String, Car> jobs) {
        this.jobs = jobs;
    }

    public List<String> getFavorites() {
        return favorites;
    }

    public void setFavorites(List<String> favorites) {
        this.favorites = favorites;
    }

    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }

}
<bean id="car1" class="spring.ioc.demo1.Car"
        p:brand="spring注入-红旗001" 
        p:color="spring注入-紫色" 
        p:maxSpeed="520" />
<bean id="boss" class="spring.ioc.iocbean.Boss">
        <property name="car">
            <ref bean="car1"></ref>
        </property>
</bean>
public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        Boss boss = ctx.getBean("boss",Boss.class);
        System.out.println(boss.getCar());
}

     

      4. null值

      如果用户想为car的brand属性注入一个null值,那么必须如下进行配置:

<bean id="car1" class="spring.ioc.demo1.Car"
     <property name="brand"><value><null/></value></property>
     <property name="color"><value>spring注入-紫色</value></property>
     <property name="maxSpeed"><value>520</value></property>
</bean>

 

      5. 集合类型属性-List  

<bean id="boss" class="spring.ioc.iocbean.Boss">
        <property name="favorites">
            <list>
                <value>电影</value>
                <value>音乐</value>
            </list>
        </property>
</bean>
public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        Boss boss = ctx.getBean("boss",Boss.class);
        
        List<String> myLove = boss.getFavorites();
        Iterator<String> it = myLove.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
输出:

  电影
  音乐

   

       6. 集合类型属性-Map

<bean id="boss" class="spring.ioc.iocbean.Boss">
     <property name="jobs">
            <map>
                <entry>
                    <key><value>getCar</value></key>
                    <ref bean="car1" />
                </entry>
            </map>
    </property>
</bean>
public static void main(String[] args) {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    Boss boss = ctx.getBean("boss",Boss.class);
    Map<String, Car> map =boss.getJobs();
    Car car = map.get("getCar");
    System.out.println(car.getColor());
}
输出:spring注入-紫色

 

      7. 集合类型属性-Properties

      Properties类型可以看成是Map类型的特列,Map类型的key和value可以为任何类型,而Properties只能为字符串。

<bean id="boss" class="spring.ioc.iocbean.Boss">  
   <property name="mails">
            <props>
                <prop key="jobMail">libininfo@360buy.com</prop>
                <prop key="lifeMail">nicholaslee@126.com</prop>
            </props>
   </property>
</bean>
public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        Boss boss = ctx.getBean("boss",Boss.class);
     Properties pro = boss.getMails();
        System.out.println(pro.get("lifeMail"));
}
输出:nicholaslee@126.com

 

      8. 通过util命名空间配置集合类型的Bean

      如果希望配置一个集合类型的Bean,而非一个集合类型的属性,则可以通过util命名空间进行配置。

      需要再Spring配置文件头中应用util命名空间的声明:

xmlns:util="http://www.springframework.org/schema/util" 
xsi:schemaLocation="
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd ">

     下面配置一个List类型的Bean,可以通过list-class显示指定List的实现类。

<!-- 配置一个集合类型的Bean,不是一个集合类型的属性 -->
<util:list id="favoriteList1" list-class="java.util.LinkedList">
        <value>看报</value>
        <value>赛车</value>
</util:list>
public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
     //读取一个集合类型的Bean,不是一个集合类型的属性
        List<String> testList = (LinkedList)ctx.getBean("favoriteList1");
        Iterator<String> itList = testList.iterator();
        while(itList.hasNext()){
            System.out.println(itList.next());
        }
}
输出:

看报
赛车

 

      9. lookup方法注入

      Spring容器拥有复写Bean方法的能力,为Bean动态创建子类或实现类。

      我们可以在singleton的Boss中注入prototype的Car,并且保证每次返回的Car对象都是最新的。

package spring.ioc.iocbean;

import spring.ioc.demo1.Car;

public interface MagicBoss {
    
    Car getCar();

}

      下面我们不编写任何实现类,仅通过配置为该接口提供动态的实现,让getCar接口每次都返回心的Car Bean.

<bean id="car1" class="spring.ioc.demo1.Car" scope="prototype"
        p:brand="spring注入-红旗001" 
        p:color="spring注入-紫色" 
        p:maxSpeed="520" />
<!-- lookup方法注入 -->
<bean id="magicBoss" class="spring.ioc.iocbean.MagicBoss">
        <lookup-method name="getCar" bean="car1"/>
</bean>
public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
     //lookup方法注入 代替实现BeanFactoryAware接口或者ApplicationContextAware接口
        MagicBoss magicBos = ctx.getBean("magicBoss",MagicBoss.class);
        System.out.println("lookup-method:"+magicBos.getCar());
}
输出:lookup-method:the car is:spring注入-红旗001, color is:spring注入-紫色, maxspeed is:520

 

      10. 实现ApplicationContextAware/BeanFactoryAware 接口

      加载Spring配置文件时,如果Spring配置文件中所定义的Bean类实现了ApplicationContextAware 接口,

      那么在加载Spring配置文件时,会自动调用ApplicationContextAware 接口中的public void setApplicationContext(ApplicationContext context) 方法,获得ApplicationContext对象,前提必须在Spring配置文件中指定该类

  <!-- ApplicationContextAware接口方式注入 -->
    <bean id="magicBossImpl2" class="spring.ioc.iocbean.MagicBossImpl2" />
package spring.ioc.iocbean;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import spring.ioc.demo1.Car;

public class MagicBossImpl2 implements MagicBoss,ApplicationContextAware {
    
    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext arg0)
            throws BeansException {
        this.applicationContext = arg0;
    }

    @Override
    public Car getCar() {
        return applicationContext.getBean("car1",Car.class);
    }

}
public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
     //实现ApplicationContextAware接口方式
        MagicBossImpl2 magicBos2 = ctx.getBean("magicBossImpl2",MagicBossImpl2.class);
        System.out.println("ApplicationContextAware:"+magicBos2.getCar());
}
输出:ApplicationContextAware:the car is:spring注入-红旗001, color is:spring注入-紫色, maxspeed is:520

      一般很少使用这种方法来每次都返回一个新的Bean,因为这样就和Spring框架耦合了,推荐使用lookup方法的注入方式。

     

      11. 方法替换

      用户可以使用某个Bean的方法去替换另一个Bean中的方法。

package spring.ioc.iocbean;

import spring.ioc.demo1.Car;

public class Boss1 {
    
    public Car getCar(){
        Car car = new Car();
        car.setBrand("垃圾车");
        return car;
    }

}
package spring.ioc.iocbean;

import java.lang.reflect.Method;

import org.springframework.beans.factory.support.MethodReplacer;

import spring.ioc.demo1.Car;

public class Boss2 implements MethodReplacer {

    @Override
    public Object reimplement(Object arg0, Method arg1, Object[] arg2)
            throws Throwable {
        Car car = new Car();
        car.setBrand("蝙蝠车");
        return car;
    }

}

      Boss2实现了MethodReplacer接口,Spring将利用接口方法去替换目标Bean中的方法。

  <!-- MethodReplacer掉包 -->
    <bean id="boss1" class="spring.ioc.iocbean.Boss1">
        <replaced-method name="getCar" replacer="boss2" />
    </bean>
    <bean id="boss2" class="spring.ioc.iocbean.Boss2" />
public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
     //MethodReplacer掉包
        Boss1 boss1 = ctx.getBean("boss1",Boss1.class);
        System.out.println(boss1.getCar().getBrand());
}
输出:蝙蝠车

     

      12. Bean的继承关系

      如果多个bean存在相同的配置信息,Spring允许我们顶一个父bean,子bean将自动继承父bean的配置信息。

<bean id="car1" class="spring.ioc.demo1.Car"
        p:brand="spring注入-红旗001" 
        p:color="spring注入-紫色" 
        p:maxSpeed="520" />
    
<!-- childCar 继承bean:car1 -->
<bean id="childCar" class="spring.ioc.demo1.Car" parent="car1"
        p:maxSpeed="1314" />
public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
     //Bean的继承
        Car childCar = ctx.getBean("childCar",Car.class);
        System.out.println("Bean的继承:"+childCar);
}
输出:Bean的继承:the car is:spring注入-红旗001, color is:spring注入-紫色, maxspeed is:1314

      说明:如果子bean提供了父bean已有的配置信息,子bean的配置信息将覆盖父bean的配置信息。

 

      以上就是在IoC容器中装配Bean的常用方法,还有别的形式大家可以跟评论。

转载于:https://www.cnblogs.com/NicholasLee/archive/2012/07/08/2581963.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值