zoukankan      html  css  js  c++  java
  • 5.Spring系列之Bean的配置2

    一、配置Bean的两种方式之使用XML配置Bean


    1.Bean的自动装配

    ①.Spring IOC 容器可以自动装配 Bean. 需要做的仅仅是在 <bean> 的 autowire 属性里指定自动装配的模式
    ②.byType(根据类型自动装配): 若 IOC 容器中有多个与目标 Bean 类型一致的 Bean. 在这种情况下, Spring 将无法判定哪个 Bean 最合适该属性, 所以不能执行自动装配.
    ③.byName(根据名称自动装配): 必须将目标 Bean 的名称和属性名设置的完全相同.
    ④.constructor(通过构造器自动装配): 当 Bean 中存在多个构造器时, 此种自动装配方式将会很复杂. 不推荐使用
     
    首先创建两个Bean,Person和Mobile:
    public class Person {
    
        private String name;
        private Mobile mobile;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Mobile getMobile() {
            return mobile;
        }
    
        public void setMobile(Mobile mobile) {
            this.mobile = mobile;
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + "]";
        }
    
    }
    public class Mobile {
    
        private String brand;
        private double price;
    
        public String getBrand() {
            return brand;
        }
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Mobile [brand=" + brand + ", price=" + price + "]";
        }
    
    }

    在IOC容器中配置byName自动装配:

    <?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"
        xmlns:p="http://www.springframework.org/schema/p"
        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-4.0.xsd">
    
        <bean id="mobile" class="com.spring.model.Mobile">
            <property name="brand" value="iphone"></property>
            <property name="price" value="5000"></property>
        </bean>
    
        <bean id="person" class="com.spring.model.Person" autowire="byName">
           <property name="name" value="loose"></property>
        </bean>
    </beans>

    byName: 若属性名和某一个 bean 的 id 名一致, 即可完成自动装配. 若没有 id 一致的, 则无法完成自动装配

    在IOC容器中配置byType自动装配:

    <?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"
        xmlns:p="http://www.springframework.org/schema/p"
        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-4.0.xsd">
        
        <!-- 无需id,根据Bean的类型自动装配 -->
        <bean class="com.spring.model.Mobile">
            <property name="brand" value="iphone"></property>
            <property name="price" value="5000"></property>
        </bean>
    
        <bean id="person" class="com.spring.model.Person" autowire="byType">
           <property name="name" value="loose"></property>
        </bean>
    </beans>

    byType: 根据类型进行自动装配. 但要求 IOC 容器中只有一个类型对应的 bean, 若有多个则无法完成自动装配

    总结:
    自动装配,即将实体内的实体(例如Person类中的Car类)自动引用;
    使用byName,只要实体内的实体名称的setXxx方法名中的Xxx和IOC容器中配置的bean id一致,即自动装配;
    使用byType,只要实体内的实体类型和IOC容器中的bean定义的类型一致即自动装配上。
    自动装配的缺点:
    --->在 Bean 配置文件里设置 autowire 属性进行自动装配将会装配 Bean 的所有属性. 然而, 若只希望装配个别属性时, autowire 属性就不够灵活了.
    --->autowire 属性要么根据类型自动装配, 要么根据名称自动装配, 不能两者兼而有之.
    注意:本身自动装配实际开发中运用不多,所以其他属性不再说明,有兴趣自己去查阅相关资料。
     
    2.继承Bean配置
    注意:
    ①.这不是java上的继承,而是配置上的继承。
    ②.Spring 允许继承 bean 的配置, 被继承的 bean 称为父 bean. 继承这个父 Bean 的 Bean 称为子 Bean
    ③.子 Bean 从父 Bean 中继承配置, 包括 Bean 的属性配置
    ④.子 Bean 也可以覆盖从父 Bean 继承过来的配置
    ⑤.父 Bean 可以作为配置模板, 也可以作为 Bean 实例. 若只想把父 Bean 作为模板, 可以设置 <bean> 的abstract 属性为 true, 这样 Spring 将不会实例化这个 Bean
    ⑥.并不是 <bean> 元素里的所有属性都会被继承. 比如: autowire, abstract 等.
    ⑦.也可以忽略父 Bean 的 class 属性, 让子 Bean 指定自己的类, 而共享相同的属性配置. 但此时 abstract 必须设为 true
    首先创建一个Bean:
    public class Person {
    
        private String name;
        private String province;
        private String city;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getProvince() {
            return province;
        }
    
        public void setProvince(String province) {
            this.province = province;
        }
    
        public String getCity() {
            return city;
        }
    
        public void setCity(String city) {
            this.city = city;
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + ", province=" + province + ", city=" + city + "]";
        }
    
    }

    接着在IOC容器中配置该Bean的信息:

    <?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"
        xmlns:p="http://www.springframework.org/schema/p"
        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-4.0.xsd">
        
        <bean id="personParent" class="com.spring.model.Person">
           <property name="name" value="loose"></property>
        </bean>
        <!-- 使用parent声明继承哪个Bean的配置 -->
        <bean id="personSon" parent="personParent"></bean>
    </beans>

    测试简单继承程序:

    public class Main {
    
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            Person person = (Person) ctx.getBean("personSon");
            System.out.println(person);
            //输出:Person [name=loose, province=null, city=null]
        }
    }

    在IOC容器中配置子Bean覆盖父Bean的信息:

    <?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"
        xmlns:p="http://www.springframework.org/schema/p"
        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-4.0.xsd">
        
        <bean id="personParent" class="com.spring.model.Person">
           <property name="name" value="loose"></property>
        </bean>
        
        <bean id="personSon" parent="personParent">
         <!-- 覆盖父Bean的name属性 --> <property name="name" value="loose2"></property> </bean> </beans>

    测试子Bean覆盖父Bean程序:

    public class Main {
    
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            Person person = (Person) ctx.getBean("personSon");
            System.out.println(person);
            //输出:Person [name=loose2, province=null, city=null]
        }
    }

    在IOC容器中将父Bean定义为模板:

    <?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"
        xmlns:p="http://www.springframework.org/schema/p"
        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-4.0.xsd">
        
        <!-- 定义为模板可以不配置class属性,但子Bean必须配置class -->
        <bean id="personParent" abstract="true">
           <property name="name" value="loose"></property>
        </bean>
        
        <bean id="personSon" class="com.spring.model.Person" parent="personParent"></bean>
    </beans>

    测试将父Bean定义为模板程序:

    public class Main {
    
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            Person person = (Person) ctx.getBean("personSon");
            System.out.println(person);
            //输出:Person [name=loose2, province=null, city=null]
        }
    }

    3.Bean的依赖配置

    Spring 允许用户通过 depends-on 属性设定 Bean 前置依赖的Bean,前置依赖的 Bean 会在本 Bean 实例化之前创建好,如果前置依赖于多个 Bean,则可以通过逗号,空格或的方式配置 Bean 的名称。
     
    4.Bean的作用域
    在 Spring 中,可以在 <bean> 元素的 scope 属性里设置 Bean 的作用域,默认情况下, Spring 只为每个在 IOC 容器里声明的 Bean 创建唯一一个实例, 整个 IOC 容器范围内都能共享该实例:所有后续的 getBean() 调用和 Bean 引用都将返回这个唯一的 Bean 实例.该作用域被称为 singleton, 它是所有 Bean 的默认作用域,常见的值有4个,分别是:
    singleton:在IOC容器中仅存在一个实例,Bean以单例的形式存在;
    prototype:每次调用getBean()都会返回一个全新的实例;
    request:每次Http请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境;
    session:同一个HttpSession共享同一个Bean,不同的HttpSession使用不同的Bean,该作用域仅适用于WebApplicationContext环境;
    最常用的是singleton和prototype!
    我们创建一个Bean为Person来测试一下:
    public class Person {
    
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + "]";
        }
    
    }

    在IOC容器中,将该Bean配置为单例:

    <?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"
        xmlns:p="http://www.springframework.org/schema/p"
        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-4.0.xsd">
        
        <bean id="person" class="com.spring.model.Person" scope="singleton">
            <property name="name" value="loose"></property>
        </bean>
    </beans>

    测试Bean单例:

    public class Main {
    
        @SuppressWarnings("resource")
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            Person person1 = (Person) ctx.getBean("person");
            Person person2 = (Person) ctx.getBean("person");
            System.out.println(person1 == person2);
            //输出true,证明是单例子
        }
    }

    在IOC容器中,将该Bean配置为prototype类型:

    <?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"
        xmlns:p="http://www.springframework.org/schema/p"
        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-4.0.xsd">
        
        <bean id="person" class="com.spring.model.Person" scope="prototype">
            <property name="name" value="loose"></property>
        </bean>
    </beans>

    测试Bean prototype:

    public class Main {
    
        @SuppressWarnings("resource")
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            Person person1 = (Person) ctx.getBean("person");
            Person person2 = (Person) ctx.getBean("person");
            System.out.println(person1 == person2);
            //输出false,证明非单例
        }
    }

    上面的例子仅仅是获取两个id一致的Bean,比较无法直观的看出IOC容器为我们的Bean创建实例的过程,接下来,我们通过一个例子再来看单例和prototype的区别:我们将Person的无参构造器显示出来

    public class Person {
    
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Person() {
            System.out.println("我是person无参构造器");
        }
        
        @Override
        public String toString() {
            return "Person [name=" + name + "]";
        }
    
    }

    接着将IOC容器中的Bean配置为单例模式:

    <bean id="person" class="com.spring.model.Person" scope="singleton">
      <property name="name" value="loose"></property>
    </bean>

    测试单例,看看控制台的输出:

    public class Main {
    
        @SuppressWarnings("resource")
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            //运行后输出:我是person无参构造器
        }
    }

    说明:单例模式是IOC一启动就帮我们实例化了Person。

    再将Bean配置为prototype,然后在看测试程序的控制台输出:

    <bean id="person" class="com.spring.model.Person" scope="prototype">
      <property name="name" value="loose"></property>
    </bean>
    public class Main {
    
        @SuppressWarnings("resource")
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            //运行后输出:没有任何输出
        }
    }

    说明:prototype模式,IOC容器启动并不会帮我们实例化Person。

    最后,我们通过获取Bean再来对比下两者的区别:

    <bean id="person" class="com.spring.model.Person" scope="singleton">
      <property name="name" value="loose"></property>
    </bean>
    public class Main {
    
        @SuppressWarnings("resource")
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            Person person1 = (Person) ctx.getBean("person");
            Person person2 = (Person) ctx.getBean("person");
            System.out.println(person1 == person2);
            //运行后输出:
            //我是person无参构造器
            //true
        }
    }
    <bean id="person" class="com.spring.model.Person" scope="prototype">
      <property name="name" value="loose"></property>
    </bean>
    public class Main {
    
        @SuppressWarnings("resource")
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            System.out.println("前面没有帮忙实例化...");
            Person person1 = (Person) ctx.getBean("person");
            Person person2 = (Person) ctx.getBean("person");
            System.out.println(person1 == person2);
            //运行后输出:
            //我是person无参构造器
            //我是person无参构造器
            //false
        }
    }

    总结:

    单例模式的Bean,IOC容器启动会自动帮我们创建了该Bean的实例,并且只创建一次;而prototype模式下IOC容器启动不会帮我们创建该Bean的实例,而是每次去getBean的时候,每次都实例化一个对象出来。

    注意:常用的是单例和prototype模式,其它的了解就行,有兴趣的自行翻阅资料。

     
  • 相关阅读:
    WyBox 7620a 启用第二个串口
    简书上关于spring boot不错的文章
    Springboot quartz集群(3) — 多节点发送邮件
    使用Gradle构建多模块SpringBoot项目
    SpringCloud的Ribbon自定义负载均衡算法
    Quartz和Spring Task定时任务的简单应用和比较
    zuul超时及重试配置
    spring cloud服务器启动之后立刻通过zuul访问其中的实例报zuul连接超时的问题
    com.netflix.zuul.exception.ZuulException:Forwarding error
    Maven项目:@Override is not allowed when implement interface method
  • 原文地址:https://www.cnblogs.com/Json1208/p/8727635.html
Copyright © 2011-2022 走看看