美文网首页
(spring)Bean的配置与注入

(spring)Bean的配置与注入

作者: 鸡龙 | 来源:发表于2019-08-13 00:09 被阅读0次

    Bean的配置

    继续引用spring中的java基础(注解)的例子代码person类和air接口。

    1、基于XML配置Bean

    Spring通过<bean>配置来实例化、设置Bean的属性以及设置bean的相互依赖,有id和class的属性,class相当于我们new来创建新实例时所需要导入的类,而id相当于创建new时的对象名。class是必须的,id是非必须的,但在配置文件中配置其他bean时引用该bean时,该bean也必须要有定义id。

    <bean id="CleanAir" class="test.model.CleanAir">
    

    2、使用注解定义Bean

    使用xml配置的时候,定义bean和实现bean是分离的,而用注解定义bean时,只要在bean实现类上标注注解就能实现配置bean。

    @Component
    public class CleanAir implements IAir {
        @Override
        public String toString(){
            return "CleanAir";
        }
    }
    

    使用@Component注解在CleanAir类声明处对类进行标注,它可以被Spring容器识别,自动将POJO类转换为容器管理的bean。他和1、中的xml配置是等效的。定义Bean的注解还提供了其他3个功能与@Component等效的注解

    • @Repository:用于对DAO实现类进行标注。
    • @Service:用于对Service实现类进行标注。
    • @Controller:用于对Controller实现类进行标注。

    3、基于Java类提供Bean定义

    在普通的pojo类中标注@Configuration注解,相当于一个xml文件配置,每个@Bean注解,相当于一个<bean>。

    @Configuration
    public class AppConf {
        @Bean
        public CleanAir cleanAir(){
            return new CleanAir();
        }
        @Bean
        public DirtyAir dirtyAir(){
            return  new DirtyAir();
        }
        @Bean
        public Person person(){
            return new Person(dirtyAir());
        }
    }
     public static void main(String [] args){
            ApplicationContext ac = 
            new AnnotationConfigApplicationContext(AppConf.class);
            Person person1 = ac.getBean(Person.class);
            person1.Breath();
        }
    

    Bean的注入

    Bean的注入方式有两种:一种是在XML中配置,另一种是使用注解的方法注入

    1、XML方式注入

    1)属性注入

    对类中的字段进行注入,在传统的对象实例化可以使用new,再进行set方法来设置字段的值,在Spring中,可以使用property来进行属性注入,需要有字段对应的set方法。

    新建XMLInstance类

    public class XMLInstance {
        private String name;
        public void setName(String name ){
            this.name = name;
        }
        private IAir iAir;
        public void setAir(IAir iAir){
            this.iAir = iAir;
        }
        public void Breath(){
            System.out.println("Name:"+this.name+"\nAir:"+this.iAir.toString());
        }
    }
    

    在XMLInstance中已设置了set方法,可以使用XMLproperty来配置属性,name表示属性名,value用来设置基本类型的属性值,ref标签配置非基本类型的属性值。XML配置如下。

     <bean id="CleanAir" class="test.model.CleanAir">
            <qualifier value="cleanair"/>
        </bean>
        <bean id="xmlinstance" class="test.model.XMLInstance">
            <property name="name" value="abc"/>
            <property name="air" ref="CleanAir"/>
        </bean>
    

    运行输出

    Name:abc
    Air:CleanAir
    

    2)构造函数注入

    在属性注入时先使用默认的无参构造函数,再使用set,在使用有参构造函数时进行的属性注入,就是构造函数注入,在1)中增加一个构造函数,在XMLInstance类中增加如下代码

    public XMLInstance(String name,IAir iAir){
            super();
            this.name = name;
            this.iAir = iAir;
        }
    

    在XML中使用construect-arg来设置构造函数的参数,index代表参数的顺序位置,value设置构造参数的基本类型,ref引用非基本类型的bean的id。XML配置如下。

    <bean id="xmlcontructinstance" class="test.model.XMLInstance">
            <constructor-arg index="0" value="def"/>
            <constructor-arg index="1" ref="CleanAir"/>
        </bean>
    

    运行输出

    Name:def
    Air:CleanAir
    

    3)工厂方法注入

    工厂方法注入参考的工厂设计模式,通过工厂类来实现对象的实例化,工厂方法有静态与非静态方法。新建一个工厂类。

    public class XMLFactory {
        public XMLInstance CreateInstance(){
            return new XMLInstance("instance",new CleanAir());
        }
        public static XMLInstance CreateStaticInstance(){
            return new XMLInstance("static instance",new CleanAir());
        }
    }
    

    可见工厂类中有静态方法和非静态方法,静态时不需要实例化工厂类直接调用静态工厂方法,非静态需要实例化工厂类再调用工厂方法。XML配置如下。

    <!--静态工厂配置-->
     <bean id="xmlstaticfactoryinstance" class="test.model.XMLFactory" 
        factory-method="CreateStaticInstance"/>
    <!--非静态工厂配置-->
        <bean id="xmlfactory" class="test.model.XMLFactory" />
        <bean id="xmlfactoryinstance" factory-bean="xmlfactory" 
        factory-method="CreateInstance"/>
    

    运行结果

    Name:static instance
    Air:CleanAir
    Name:instance
    Air:CleanAir
    

    4)常见数据类型注入

    已有类型注入

    常见数据类型有List、Set、Map、Properties。
    新建XmlCollectionsDemo类,为这四种类型进行数据注入。

    public class XmlCollectionsDemo {
        private List<Object> list;
        private Properties pros;
        private Set<Object> sets;
        private Map<String,Object> maps;
        public List<Object> getList() {
            return list;
        }
        public void setList(List<Object> list) {
            this.list = list;
        }
        public Properties getPros() {
            return pros;
        }
        public void setPros(Properties pros) {
            this.pros = pros;
        }
        public Set<Object> getSets() {
            return sets;
        }
        public void setSets(Set<Object> sets) {
            this.sets = sets;
        }
        public Map<String, Object> getMaps() {
            return maps;
        }
        public void setMaps(Map<String, Object> maps) {
            this.maps = maps;
        }
        public static void main(String[] args){
            ApplicationContext ac = new ClassPathXmlApplicationContext("META-INF/model.xml");
            BeanFactory factory = ac;
            XmlCollectionsDemo xmlCollectionsDemo
                    = (XmlCollectionsDemo)factory.getBean("xmlCollectionsDemo");
            System.out.println(xmlCollectionsDemo.getList());
            System.out.println(xmlCollectionsDemo.getPros());
            System.out.println(xmlCollectionsDemo.getSets());
            System.out.println(xmlCollectionsDemo.getMaps());
            System.out.println(xmlCollectionsDemo.getDate());
        }
    }
    

    XML配置

    <bean id="xmlCollectionsDemo" class="test.model.XmlCollectionsDemo">
    <!--        list类型注入-->
            <property name="list">
                <list>
                    <value>1</value>
                    <ref bean="CleanAir"/>
                    <bean class="test.model.CleanAir"/>
                </list>
            </property>
            <!-- set类型注入-->
            <property name="sets">
                <set>
                    <value>1</value>
                    <ref bean="CleanAir"/>
                    <bean class="test.model.CleanAir"/>
                </set>
            </property>
            <!-- pros类型注入-->
            <property name="pros">
                <props>
                    <prop key="prokey1">prokeyA</prop>
                    <prop key="prokey2">prokeyB</prop>
                </props>
            </property>
            <!-- maps类型注入-->
            <property name="maps">
                <map>
                    <entry key="key1" value="1"></entry>
                    <entry key="key2" value-ref="CleanAir"></entry>
                    <entry key="key3" >
                        <bean class="test.model.CleanAir"/>
                    </entry>
                </map>
            </property>
    

    运行结果

    [1, CleanAir, CleanAir]
    {prokey2=prokeyB, prokey1=prokeyA}
    [1, CleanAir, CleanAir]
    {key1=1, key2=CleanAir, key3=CleanAir}
    
    自定义属性编辑器

    有一些属性是没法注入的,比如说日子。但可以通过PropertyEditorySupport,重写setAsText方法来实现注入。新建CustomerProperty类

    public class CustomerProperty extends PropertyEditorSupport {
        private String format = "yyyy-MM-dd";
        public String getFormat(){
            return format;
        }
        public void setFormat(String format){
            this.format = format;
        }
        @Override
        public void setAsText(String text) throws IllegalArgumentException{
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            try{
                this.setValue(sdf.parse(text));
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    
    <bean id="customEditorConfigurer" 
     class="org.springframework.beans.factory.config.CustomEditorConfigurer">
            <property name="customEditors">
                <map>
                    <entry key="java.util.Date" value="test.model.CustomerProperty"/>
                </map>
            </property>
        </bean>
    

    该类中将日期以String的形式传入,再重写了setAsText方法,setAsText方法会自动执行转换成日期类重新赋值给传入的value,在XML配置中,相当于import,将Date类引用到customEditors中。将4)中XmlCollectionsDemo添加字段Date,并在xml中增加

    <property name="date" value="2019-8-12"/>
    

    运行结果

    [1, CleanAir, CleanAir]
    {prokey2=prokeyB, prokey1=prokeyA}
    [1, CleanAir, CleanAir]
    {key1=1, key2=CleanAir, key3=CleanAir}
    Mon Aug 12 00:00:00 CST 2019
    

    5)初始化函数、销毁函数

    在某些对象实例化完毕后还需要执行某些初始化代码,但由于某些原因并不能写在构造函数中,这个时候可以使将初始化代码写到另一个方法中,将init-method属性设置为该方法,有的对象使用完毕之后需要释放操作,可以用destroy-method设置销毁方法

    在XMLInstance类中增加初始化方法和销毁方法

        public void DestroyMethod(){
            System.out.println("DestroyMethod");
        }
        public void InitMethod(){
            System.out.println("InitMethod");
        }
    

    并在XML中注入初始化方法和销毁方法,修改xml

     <bean id="xmlinstance" class="test.model.XMLInstance" 
              destroy-method="DestroyMethod" init-method="InitMethod">
            <property name="name" value="abc"/>
            <property name="air" ref="CleanAir"/>
        </bean>
    

    这样在创建实例后会输出InitMethod,在执行销毁之后会输出DestroyMethod。

    2、注解方式注入

    1)常用注解

    • @Autowired:默认按类型匹配注入bean,可以对类成员变量、方法和构造函数进行标注,完成自动装配的工作。在使用该注解时,会在容器中查询对应类型的bean。如果查询结果刚好为一个,就将该bean装配给他指定的数据:如果查询结果不止一个,会按照名称来查找,如果查询结果为空,会抛出异常。
    • @Required:适用于bean属性的setter方法,并表示受影响的bean属性必须在XML配置文件在配置时进行填充:否则会抛出一个异常。
    • @Qualifier:@Autowird为单实例的,但通常在面向接口编程中,一个接口会有可能有多个实现,这个时候@Qualifier可选择用哪个实现进行注入。
    • @Value:等效于property中的value设置。
    • @Resource:默认按名称匹配注入bean。要求提供一个bean名称,如果没有提供bean名称,会自动采用标注处的变量名或方法名作为bean的名称,如果没有指定bean的名字,同时Spring容器中又没有该名字的bean.这时@Resource会退回为@Autowired按类型匹配注入。

    新建一个AnnontationInstance类

    @Component
    public class AnnontationInstance {
        @Value("789")
        private String name;
    
        public void setName(String name){
            this.name = name;
        }
        @Autowired
        @Qualifier(value = "cleanair")
    
        private IAir air;
    //    @Resource(name = "CleanAir")
        public void setAir(IAir air){
            this.air = air;
        }
        public void Breath(){
            System.out.println("Name:"+this.name+"\nAir:"+this.air.toString());
        }
    }
    

    注:@Autowired和@Qualifier是可以与@Resource相互代替使用的,但是在@Resource中使用的是name是bean的id,而@Qualifier中的valu使用的是bean的qualifier。

    回顾xml

    <bean id="CleanAir" class="test.model.CleanAir">
            <qualifier value="dirtyair"></qualifier>
        </bean>
        <bean id="DirtyAir" class="test.model.DirtyAir">
            <qualifier value="cleanair"></qualifier>
        </bean>
    

    在配置完注解之后,还要告诉Spring开启注解,这样自动装配的注解才会生效,可以使用component-scan或者annotation-config来启用注解

     <context:component-scan base-package="test.model"/>
    
    <context:annotation-config/>
    

    相关文章

      网友评论

          本文标题:(spring)Bean的配置与注入

          本文链接:https://www.haomeiwen.com/subject/abdmjctx.html