Spring 中的 Bean

上一篇主要讲了IOC反转控制,也就是程序中有些东西用XML文档配置去关联,而不是在类本身里面写明!
 这篇接着写注入的形式!我们先在上次的项目中修改!继续在fengyan包下添加一个Home.java类:
Home.java
然后在User.java中添加一Home属性
User.java
将 Home Bean的信息添加到applicationContext.xml中
    <bean id="home" class="fengyan.Home" abstract="false"
        singleton
="true" lazy-init="default" autowire="default"
        dependency-check
="default">
        
<property name="address">
            
<value>湖北 武汉</value>
        
</property>
    
</bean>
自然的,User Bean的配置 信息中就少了一个myhome属性:
<bean id="user" class="fengyan.User" abstract="false"
        singleton
="true" lazy-init="default" autowire="default"
        dependency-check
="default">
        
<property name="userName">
            
<value>efly</value>
        
</property>
     
</bean>
我们应该添加myhome,但此时myhome为一对象应该用ref引用,如下
    <bean id="user" class="fengyan.User" abstract="false"
        singleton
="true" lazy-init="default" autowire="default"
        dependency-check
="default">
        
<property name="userName">
            
<value>efly</value>
        
</property>
        
<!-- 添加一个属性 -->
        
<property name="myhome">
            
<ref bean="home"/><!-- home为上面注入的bean id -->
        
</property>
     
</bean>
最后完整的applicationContext.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
    
    
<bean id="home" class="fengyan.Home" abstract="false"
        singleton
="true" lazy-init="default" autowire="default"
        dependency-check
="default">
        
<property name="address">
            
<value>湖北 武汉</value>
        
</property>
    
</bean>
    
    
<bean id="user" class="fengyan.User" abstract="false"
        singleton
="true" lazy-init="default" autowire="default"
        dependency-check
="default">
        
<property name="userName">
            
<value>efly</value>
        
</property>
        
<!-- 添加一个属性 -->
        
<property name="myhome">
            
<ref bean="home"/><!-- home为上面注入的bean id -->
        
</property>
     
</bean>
    
</beans>

而运行的测试文件仅仅加入System.out.println(user.getMyhome().getAddress());即可得到注入的地址

package fengyan;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

/**
 * 
 * 
@author: fengyan
 * date:     2006-12-31 02:39
 *
 
*/

public class TestMain {

    
public static void main(String[] args){
        
/*
        //依赖注入
        User user = new User();
        user.setUserName("fengyan");        
        System.out.println(user.getUserName());
        
*/

        
//ICO 反转控制
        ApplicationContext context = new FileSystemXmlApplicationContext("fengyan/applicationContext.xml");
        
//这样我们获取了一个全局的应用程序上下文对象
        
        
//下面我们创建实例就不是先前的直接new 了
        User user = (User)context.getBean("user");//是对象类型,需转换
        System.out.println(user.getUserName());
        System.out.println(user.getMyhome().getAddress());
    }


}

另外还有构造函数的注入,如何通过一构造函数的注入呢?假设现在我将 上在applicationContext.xml文件中user属性myhome去掉,然后在User.java中写一构造函数,
//构造函数的注入
    public User(Home myhome)
    
{
        
this.myhome = myhome;
    }
那么这个时候该User实例化时需要一个参数,那么如何做呢?

我们将applicationContext.xml文件中user  bean的属性autowire由默认的default改为consctructor也就是构造,
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
    
    
<bean id="home" class="fengyan.Home" abstract="false"
        singleton
="true" lazy-init="default" autowire="default"
        dependency-check
="default">
        
<property name="address">
            
<value>湖北 武汉</value>
        
</property>
    
</bean>
    
    
<bean id="user" class="fengyan.User" abstract="false"
        singleton
="true" lazy-init="default" autowire="constructor"
        dependency-check
="default">
        
<property name="userName">
            
<value>efly</value>
        
</property>
        
        
<!-- 添加一个属性 
        <property name="myhome">
            <ref bean="home"/>  home为上面注入的bean id 
        </property>
-->
     
</bean>
    
</beans>

此时我们直接运行,发现依然成功!得到了“湖北 武汉”,为什么它能自动输出呢,也就是我们的User.java中本身有二个属性 userName 和myhome,其中有一个属性我们设定了,另外一个没有设定,这时它就会去找,那么找的时候有下面几种方式,这里我说说bean中的autowire属性,它有以下几种取值:
autowire="byType",可以使bean在运行的时候根据需要去寻找同类型的已经在applicationContext.xml中定义了的属性,如果找不到,则处于未绑定状态。
autowire="byName",可以使bean在运行时根据需要去寻找同名的已在applicationContext.xml中定义的属性,如果找不到处于未绑定状态。
autowire="autodetect":这个是一个个式,直到找到合适的!
autowire="constractor",可以使bean在运行的时候根据已在applicationContext.xml中定义的的属性去寻找相关的构造方法属性,如果找不到则牌未绑定状态,它使用的是byType,
我们如果将autowire="constractor"改为byType,如果我们定义了多个Home类型的bean则运行的时候会出错,因为有多个类型满足条件!这时可以换为byName,aotuwrie="byName"这里的name是哪里的呢?这里的名字应该是User.java类中定义的属性 private Home myhome;的 myhome同名即可!这时要注意一下,在User.java中加入一个无参数的构造函数!

这时如果我们将注入的user  bean复制一份 user2,那么在程序中就可以输出user和user2的内容完全一样,但它们的getMyhome()的Home对象是不是同一个注入的myhome对象呢,我们可以用user.getMyhome().hashcode();发现是完全一样的,由此可知它们所使用的是同一个Home对象!
这样我们明白一件事情,就是上面我们注入的myhome Bean只创建了一次,那么什么时候会创建一次,什么时候会创建多次呢,我们可以看到在bean  中有一属性singleton,在设计模式中也有这样一种模式,单例模式!由此可知如果我们将 真值改为false,则就会在程序运行中创建多个myhome Bean

这时我们再改改,将User.java中的Home属性 ,改为Home[] myhome,以为一集合!或者说是一列,集合,MAP怎么办,

User.java

在applicationContext.xml中添加Home[]信息,如下:
    <property name="myhome">
             
<list>
                 
<ref bean="home"/>
                 
<ref bean="myhome"/>
             
</list>
        
</property>
TestMain.java运行 文件中如下读取:
    //对象集合演示
        Home[] homes = (Home[])(user.getMyhome());
        
for(int i = 0 ; i < homes.length; i++)
        
{
            System.out.println(homes[i].getAddress());
        }

这时我们得到正确输出!这时说明数组成功了!

这是对象集合,那么List呢,我们再在配置文件中将user Bean添加一属性:

            <property name="myhomeList">
                
<list>
                    
<ref bean="myhome" />
                    
<value>HAHAXIXItest</value>
                    
<ref bean="home" />
                
</list>
            
</property>

可知该List中有对象也有普通值!在TestMain中我们这样使用:
    //List 集体演示
        List myList = (List)user.getMyhomeList();
        Iterator it 
= myList.iterator();//跌代器
        while(it.hasNext())
        
{
            System.out.println(it.next().toString());
        }
接下来中SET,如何做,其实和List差不多。在配置文件中user Bean添加一属性
<property name="myhomeSet">
                
<set>
                    
<ref bean="myhome" />
                    
<value>setvalue</value>
                
</set>
            
</property>
在运行类中使用如下代码测试:
        //Set演示
        Set myset = (Set)user.getMyhomeSet();
        Iterator it1 
= myset.iterator();
        
while(it1.hasNext())
        
{
            System.out.println(it1.next().toString());
        }
最后一个也是相对比较麻烦的一个!我们使用OutLine可视化做,如图,

它是键值对的形式,我们添加一个KEY:t1值为对象类型,。我们引用的上面注入的myhome  Bean!
配置文件user  Bean添加的属性代码如下
<property name="myhomeMap">
                
<map>
                    
<entry key="t1">
                        
<ref bean="myhome" />
                    
</entry>
                    
<entry key="t2" value="mapTest"></entry>
                
</map>
            
</property>
而测试运行代码如下:
//Map演示
        Map mymap = (Map)user.getMyhomeMap();
        System.out.println( ( (Home)(mymap.get(
"t1")) ).getAddress() );//通过主键找
这样也就运行到了结果!最后将完整的代码贴出:
User.java

TestMain.java

applicationContext.xml
原文地址:https://www.cnblogs.com/eflylab/p/609024.html