zoukankan      html  css  js  c++  java
  • Spring的Bean配置

    IOC和DI

        网上概念很多,感兴趣可以去搜一搜,在这里我就给个比喻:

    IOC:以前我们买东西都要去商店买,用了IOC之后,我们只要在门口放个箱子, Spring就会给我相应商品,

    举个例子

    1. class A{}  
    2.     
    3. class B{  
    4.     private A a;  
    5.     public void setA(A a){  
    6.          this.a=a;  
    7.     }  
    8. }  

    在传统的写法中,在创建A B对象,他们之间的关联需要我们手动设置,b.set(a),而在使用Spring之后,这一步就不需要了,由框架为我们设置相关内容

    IOC的发展:

    1. 分离接口与实现
    2. 工厂设计模式
    3. 翻转控制

    基于XML配置bean

        <bean>中的class属性填入bean的全类名,通过反射方式在IOC容器中创建Bean,所以要求Bean中必须有无参的构造函数。

        属性id用来表示容器中的id,id唯一

        ApplicationContext代表IOC容器,实际这是一个接口。在SpringIOC容器读取Bean配置创建Bean实例之前,必须对它进行实例化,只有在容器实例化后,才可以从IOC容器里获取Bean实例并使用。

        Spring为我们提供了两种类型的IOC容器实现:

    1. BeanFactory:IOC容器的基本实现
    2. ApplicationContext:提供了更多高级特性,是BeanFactory的子接口
    3. ClassPathXmlApplicationContext是ApplicationContext的实现类

    BeanFactory是Spring的基础设施,面向Spring本身,ApplicationContext面向Spring框架开者,几乎所有应用场合都直接使用ApplicationContext而非底层BeanFactory,当然,无论使用何种方式,配置文件都相同。

    ApplicationContext的主要实现类:

    ClassPathXmlApplicationContext:从类路径下加载配置文件

    FileSystemXmlApplicationContext:从文件系统中加载配置文件

     

    ConfigurableApplicationContext扩展于ApplicationContext,新增两个主要方法:refresh()和close(),让ApplicationContext具有启动/刷新和关闭上下文的功能。

    ApplicationContext在初始化上下文时就实例化所有单例的Bean。

    WebApplication是专门为WEB应用而准备的,它允许从相对于WEB根目录的路径中完成初始化工作。

    接下来说说getBean()这个方法,getBean()这个方法实际是存在在BeanFactory这个接口中,我们看看下面这张截图:

     

    非常多个重载,我们在之前的例子中也可以这么写,利用类型返回IOC容器:

    HelloWorld helloWorld = ctx.getBean(HelloWorld.class);

    也是没问题的,这样有缺点吗?

    加入我在配置文件中创建了两个<bean>并且都是HelloWorld的JavaBean,这样Spring就识别不出是哪一个<bean>了,因此不推荐这么写,推荐通过id名返回IOC容器,创建对象

    HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");

    依赖注入

    1. 属性注入
    2. 构造器注入
    3. 工厂方法注入(很少使用,不推荐)

    先说说最常用的属性注入,这个属性注入就是我们先前HelloWorld中使用的方法,通过setter方法注入Bean的属性值或依赖的对象,通过<property>标签,使用name指定Bean的属性名称,value属性指定属性值

    <property name="name" value="World"></property>

     

    接着说构造方法注入,通过构造方法注入Bean的属性值或依赖对象,它保证了Bean实例在实例化后就可以使用。

    构造器注入需要用<constructor-arg>元素里声明属性,注意<constructor-arg>中没有name属性

    我们新创建Car类作为测试:

    1. public class Car {  
    2.     private String brand;  
    3.     private String corp;  
    4.     private Integer price;  
    5.     private Integer maxSpeed;  
    6.     
    7.     public Car(String brand, String corp, Integer price) {  
    8.         this.brand = brand;  
    9.         this.corp = corp;  
    10.         this.price = price;  
    11.     }  
    12.     
    13.     @Override  
    14.     public String toString() {  
    15.         return "Car{" +  
    16.                 "brand='" + brand + ''' +  
    17.                 ", corp='" + corp + ''' +  
    18.                 ", price=" + price +  
    19.                 ", maxSpeed=" + maxSpeed +  
    20.                 '}';  
    21.     }  
    22. }  

    这里故意在构造器里少放一个字段,来到配置文件

    1. <bean id="car" class="com.figsprite.bean.Car">  
    2.     <constructor-arg value="奥迪"></constructor-arg>  
    3.     <constructor-arg value="上海"/>  
    4.     <constructor-arg value="3000000"/>  
    5. </bean>  

    在Main中输入测试代码:

    1. Car car = (Car)ctx.getBean("car");  
    2. System.out.println(car.toString());  

    看结果,很有意思的是我已经将HelloWorld.java相关的代码注释了,可是还是出现了我们上一讲所写的注释,这就应证了之前所说的:

    ApplicationContext在初始化上下文时就实例化所有单例的Bean。

    接下来再配置一个构造器:

    1. public Car(String brand, String corp, int price, int maxSpeed) {  
    2.     this.brand = brand;  
    3.     this.corp = corp;  
    4.     this.price = price;  
    5.     this.maxSpeed = maxSpeed;  
    6. }  

      来到配置文件:

    7. <bean id="car2" class="com.figsprite.bean.Car">  
    8.     <constructor-arg value="海南马自达"></constructor-arg>  
    9.     <constructor-arg value="上海"/>  
    10.     <constructor-arg value="3000000"/>  
    11.     <constructor-arg value="78"/>  
    12. </bean>  
    1. Car car2 = (Car)ctx.getBean("car2");  
    2. System.out.println(car2.toString());  

    发现没什么问题,但如果构造器是品牌名、场地、最大速度,Spring能识别出来吗?

    先将price改成double,否则不满足重载规则,写上新的配置文件

    1. <bean id="car2" class="com.figsprite.bean.Car">  
    2.     <constructor-arg value="海南马自达"></constructor-arg>  
    3.     <constructor-arg value="上海"/>  
    4.     <constructor-arg value="78"/>  
    5. </bean>  

    发现并没有得到我们想要的,如何解决这个问题呢?

     

    此时需要用到type属性,

    1. <bean id="car" class="com.figsprite.bean.Car">  
    2.     <constructor-arg value="奥迪" type="java.lang.String"></constructor-arg>  
    3.     <constructor-arg value="上海" type="java.lang.String"/>  
    4.     <constructor-arg value="3000000" type="double"/>  
    5. </bean>  
    6.     
    7. <bean id="car2" class="com.figsprite.bean.Car">  
    8. <constructor-arg value="海南马自达" type="java.lang.String"></constructor-arg>  
    9. <constructor-arg value="上海" type="java.lang.String"/>  
    10. <constructor-arg value="78" type="int"/>  
    11. </bean>  

    嗯,是我们想要的了,使用构造器注入属性值可以指定参数的位置和参数类型,这里还有一个index的属性,用于不按构造器参数顺序写标签时使用。大家可以自行尝试一下

  • 相关阅读:
    Docker三剑客之 Compose
    cloudrea manager 调整datanode数据存储目录
    Docker Dockerfile 定制镜像(转)
    Docker配置mysql互为主从
    Docker构建redis cluster集群
    Kubernetes集群向指定节点上创建容器
    Docker私有仓库registry的搭建及使用
    Docker简介及基本应用
    Kubernetes的UI界面Kubernetes Dashboard的搭建
    java垃圾回收机制
  • 原文地址:https://www.cnblogs.com/figsprite/p/10756140.html
Copyright © 2011-2022 走看看