• Spring学习笔记14---bean的使用


    前言

    Spring最基础的功能就是一个bean工厂,所以本文讲解的是Spring生成bean的种种方法及细节,Spring配置文件的名字是bean.xml,定义几个类:

    一个Person类:

     
    public class Person
    {
        private String     personName; // 人的名字
        private int        personAge;    // 人的年龄    
        
        public Person(String personName, int personAge)
        {
            this.personName = personName;
            this.personAge = personAge;
        }
    
        public String getPersonName()
        {
            return personName;
        }
        
        public void setPersonName(String personName)
        {
            this.personName = personName;
        }
        
        public int getPersonAge()
        {
            return personAge;
        }
    
        public void setPersonAge(int personAge)
        {
            this.personAge = personAge;
        }
    
        public String toString()
        {
            return "personName = " + personName + ", personAge = " + personAge;
        }
    }
     

    一个Family类,里面持有Person的引用:

     
    public class Family
    {
        private Person person;
        private String familyName;
    
        public Family(Person person, String familyName)
        {
            this.person = person;
            this.familyName = familyName;
        }
    
        public String toString()
        {
            return person.toString() + ", familyName = " + familyName;
        }
    }
     

    一个单例类:

     
    public class SingletonClass
    {
        private SingletonClass instance = new SingletonClass();
        
        private SingletonClass(){}
        
        public SingletonClass getInstance()
        {
            return instance;
        }
    }
     

    一个空的类,为了测试初始化和销毁用的:

     
    public class EmptyClass
    {
        static
        {
            System.out.println("Enter EmptyClass.static block");
        }
        
        public EmptyClass()
        {
            System.out.println("Enter EmptyClass.construct()");
        }
        
        public void init()
        {
            System.out.println("Enter EmptyClass.init()");
        }
        
        public void destory()
        {
            System.out.println("Enter EmptyClass.destory()");
        }
    }
     

    一个集合类,为了演示集合注入:

     
    public class CollectionClass
    {
        private List<String> list;
        private Map<Family, Person> map;
        private int[] ints;
        
        public List<String> getList()
        {
            return list;
        }
        
        public void setList(List<String> list)
        {
            this.list = list;
        }
        
        public Map<Family, Person> getMap()
        {
            return map;
        }
        
        public void setMap(Map<Family, Person> map)
        {
            this.map = map;
        }
    
        public int[] getInts()
        {
            return ints;
        }
    
        public void setInts(int[] ints)
        {
            this.ints = ints;
        }
    }
     

    最简单的bean实例化

    bean.xml中注入这个bean,以Person类为例:

     
    <?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-4.2.xsd">
        
        <bean id="person" class="com.xrq.bean.Person" />
        
    </beans>
     

    main函数这么写:

     
    public static void main(String[] args)
    {
        ApplicationContext ctx = 
                new ClassPathXmlApplicationContext("spring.xml");
        Person person1 = (Person)ctx.getBean("person");
        Person person2 = (Person)ctx.getBean("person");
        System.out.println(person1 == person2);
    }
     

    运行结果为true,也就是说Spring默认以单例的形式给开发者构造出指定的bean。另外有两点要注意:

    1、同一个spring.xml中不可以定义两个id相同的bean

    2、ClassPathXmlApplicationContext中有一个可变长度的构造函数,用于加载多个.xml中的bean,如果bean中有id相同,那么id相同的bean,后加载的会覆盖先加载的

    bean的作用域及生命周期

    代码不动,把bean.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-4.2.xsd">
        
        <bean id="person" class="com.xrq.bean.Person" scope="prototype"
            lazy-init="true"/>
        
    </beans>
     

    这里出现了两个属性,scope和lazy-init:

    1、scope表示的是bean的作用域,有prototype、request、session、singleton四种,其中singleton是默认的,表示单例。prototype表示每次创建都会产生一个bean实例。request和session只在web项目中才会用,其作用域就和web中的request和session一样

    2、lazy-init表示的是bean的生命周期,默认为false。当scope=singleton时,bean会在装在配置文件时实例化,如果希望bean在产生时才实例化,可以把lazy-init设置为true。当scope=prototype时,在产生bean时才会实例化它。补充一点,如果希望该配置文件中所有的bean都延迟初始化,则应该在beans根节点中使用lazy-init="true"

    三种注入方式

    所谓注入即注入bean中的属性,Spring为用户提供了三种注入方式,settter注入、构造方法注入、注解注入,不过对于Spring的讲解,不讲注解,所以看一下前两种注入方式:

    1、setter注入,bean.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-4.2.xsd">
        
        <bean id="person" class="com.xrq.bean.Person">
            <property name="personName" value="Alice"/>
            <property name="personAge" value="10" />
        </bean>    
    </beans>
     

    2、构造方法注入,bean.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-4.2.xsd">
        
        
        <bean id="family" class="com.xrq.bean.Family">
            <constructor-arg name="person" ref="person" />
            <constructor-arg name="familyName" value="friendly" />
        </bean>
        
        <bean id="person" class="com.xrq.bean.Person">
            <property name="personName" value="Alice"/>
            <property name="personAge" value="10" />
        </bean>    
    </beans>
     

    这里故意把family的定义写在person的定义上面,说明即使前面的beanA持有beanB的引用,把beanA定义在beanB前面也不影响

    集合注入

    spring对于集合属性的支持非常好,以CollectionClass为例,看下如何配置bean.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-4.2.xsd">
        
        <bean id="collectionClass" class="com.xrq.bean.CollectionClass">
            <property name="list">
                <list>
                    <value>111</value>
                    <value>222</value>
                </list>
            </property>
            <property name="map">
                <map>
                    <entry key="111">
                        <bean class="com.xrq.bean.Person">
                            <property name="personName" value="Mike"/>
                            <property name="personAge" value="11" />
                        </bean>
                    </entry>
                </map>
            </property>
            <property name="ints">
                <array>
                    <value>333</value>
                    <value>444</value>
                </array>
            </property>
        </bean>
    </beans>
     

    工厂方式生成类

    Spring虽然可以指定bean以单例的方式生成出来,但是每次都要用getBean方法获取类的实例非常麻烦,有办法像单例模式一样使用XXX.getInstance()就好了,不过还真有,以SingletonClass作为例子:

     
    <?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-4.2.xsd">
        
        <bean id="singletonClass" class="com.xrq.bean.SingletonClass"
            factory-method="getInstance">
        </bean>
        
    </beans>
     

    这样,我们就可以使用单例的方式去调用这个类了,如果类里面有一些私有属性,还可以注入的方式在生成这个bean的时候就注入进去,非常方便

    init-method和destory-method

    有时候我们希望,在某个bean加载的时候做一些事情,销毁的时候做一些事情(是不是想到了Servlet),所以我们可以自定义初始化和销毁的方法EmptyClass这个类,bean.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-4.2.xsd">
            
        <bean id="emptyClass" class="com.xrq.bean.EmptyClass" 
            init-method="init" destroy-method="destory"/>
    </beans>
     

    注意两点:

    1、实例化类的时候,几个方法的加载顺序为静态资源->构造方法->初始化方法

    2、触发destory()方法的调用可以使用"((ClassPathXmlApplicationContext)ctx).close();",注意scope="prototype"是不会触发destory()的,没有为什么,设计就是这样

    父子类继承关系

    有时候我们有要求,一个类是某一个类/抽象类的子类,可以这么做:

    public abstract class AbstractClass
    {
    
    }
    public class ImplClass extends AbstractClass
    {
    
    }

    此时bean.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-4.2.xsd">
        
        <bean id="abstractClass" class="com.xrq.bean.abstractClass" abstract="true"/>
        <bean id="implClass" class="com.xrq.bean.ImplClass" parent="abstractClass" />
    </beans>
     

    注意这种写法对接口也有效。

    ================================================================================== 

    我不能保证写的每个地方都是对的,但是至少能保证不复制、不黏贴,保证每一句话、每一行代码都经过了认真的推敲、仔细的斟酌。每一篇文章的背后,希望都能看到自己对于技术、对于生活的态度。

    我相信乔布斯说的,只有那些疯狂到认为自己可以改变世界的人才能真正地改变世界。面对压力,我可以挑灯夜战、不眠不休;面对困难,我愿意迎难而上、永不退缩。

    其实我想说的是,我只是一个程序员,这就是我现在纯粹人生的全部。
  • 相关阅读:
    Centos7 定时任务
    Linux启动配置文件和运行等级runlevel
    Linux 网卡命名规则
    将博客搬至CSDN
    Lua调用C++动态链接库.so
    使用shell脚本执行批量mongosh语句
    TCP和UDP详解
    经受时延的确认(Delay ACK)
    18张图带你了解衡量网络性能的四大指标:带宽、时延、抖动、丢包
    TCP学习
  • 原文地址:https://www.cnblogs.com/huangyangquan/p/8600779.html
Copyright © 2020-2023  润新知