Spring的IOC容器以及Bean的配置

1.什么是Spring

spring是一个为简化企业开发而生的开源框架,我们使用Spring可以很简单、优雅地完成同样在EJB中要通过繁锁的配置和复杂的代码才能够实现的功能,不仅如此,Spring还是一个IOC(DI)和AOP容器。而且在IOC和AOP的基础上,Spring可以整合各种企业应用的开源框架和优秀的第三方类库。

2.Spring的IOC容器

2.1 IOC(Inversion of Control):控制反转

IOC也就是控制反转,他是Spring中的一种思想,通俗的来讲就是Spring技术将原本资源获取的方向进行了反转,由之前的组件主动的从容器中获取所需要的资源,变成了容器主动的将资源推送给需要的组件,这种行为也称为查找的被动形式。这样很大的提高了开发的效率,这就是Spring受欢迎的原因。

2.2 DI(Dependency Injection):依赖注入

依赖注入即组件以一些预先定义好的方式接受来自Spring容器的资源注入。DI其实就是IOC思想的一种具体实现,相对于IOC,DI的这种表述更为直接。

3.IOC容器在Spring中的实现

在Spring的IOC容器读取Bean的实例之前,Spring需要先将IOC容器本身实例化,Spring实例化IOC容器一般运用BeanFactory的子接口ApplicationContext。ApplicationContext所用到的主要实现类有ClassPathXmlApplicatinContext、FileSystemXmlApplicationContext、ConfigurableApplicationContext以及WebApplicationContext。

4.给bean的属性赋值 

Spring首先调用ClassPathXmlApplicationContext实例化IOC容器,然后Sring IOC容器会读取bean的配置信息,拿到bean的配置信息之后在Spring容器中定义注册表,下一步Spring根据bean注册表实例化Bean对象,然后将bean的实例放到Spring容器中,供应用程序使用。

下面将介绍基于 XML 的配置文件来为bean赋值的几种方式:

4.1 依赖注入的方式为bean的属性赋值:(通过bean的set方法赋值)

首先编写我们的实体类:Person,在实体类中我们实现成员变量的getter、setter和tostring方法,然后写一个SayHello方法,输出一句话。

public class Person {
    private String name;        

    public Person() {
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }


    public void SayHello(){
        System.out.println("我的名字叫做"+name);
    }
}

然后配置我们的xml文件,为bean赋值。

idea中创建spring的配置文件的步骤:File--New--XML ConfigurationFile--Spring Config。配置如下:

扫描二维码关注公众号,回复: 8956572 查看本文章
<?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.xsd">

  
    <bean id="person" class="com.wei.springHelloword.bean.Person">
        <property name="name" value="张三"></property>
    </bean>

</beans>

最后我们编写测试类:Test

public class Test {

    public static void main(String[] args) {
        //1.创建spring的ioc对象
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        //获得Person对象  可以方法重载

        Person person = ctx.getBean("person", Person.class);
        //调用方法

       person.SayHello();

    }

}

结果:

一月 28, 2020 11:23:12 上午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@37f8bb67: startup date [Tue Jan 28 11:23:12 CST 2020]; root of context hierarchy
一月 28, 2020 11:23:12 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
我的名字叫做张三

Process finished with exit code 0

4.2 通过bean的构造器赋值

首先创建实体类Car,通过构造器赋值需要创建有参构造器和无参构造器,缺一不可。

public class Car {
    private String brand;
    private String crop;
    private Double price;
    

    public Car(){

    }

    public Car(String brand, String crop, Double price) {
        this.brand = brand;
        this.crop = crop;
        this.price = price;
    }


    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", crop='" + crop + '\'' +
                ", price=" + price +
                '}';
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getCrop() {
        return crop;
    }

    public void setCrop(String crop) {
        this.crop = crop;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

}

编写xml文件为bean赋值

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

<!--    DI依赖注入的方式:构造器的方式-->
<!--    index:指定参数位置
        type:指定参数类型
-->
    <bean id="car1" class="com.wei.springDI.bean.Car">
        <constructor-arg value="宝马" index="0"></constructor-arg>
        <constructor-arg value="华晨"></constructor-arg>
        <constructor-arg value="450000" type="java.lang.Double"></constructor-arg>
    </bean>



</beans>

测试:

public class Test {   
    @Test
    public void Testset(){
        ClassPathXmlApplicationContext cxt = 
                         new ClassPathXmlApplicationContext("application-di.xml");
        Car car = cxt.getBean("car", Car.class);
        System.out.println(car);
    }
}

4.3 p命名空间来为bean赋值

为了简化XML文件的配置,越来越多的XML文件采用属性而非子元素配置信息。Spring从2.5版本开始引入了一个新的p命名空间,可以通过<bean>元素属性的方式配置Bean的属性。

首先需要引入p命名空间的依赖:xmlns:p="http://www.springframework.org/schema/p"

还是用Car的实体类。

xml配置文件为bean赋值:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">


    <!--p命名空间,底层还是调用set方法 -->
    <bean id="car3" class="com.wei.springDI.bean.Car"
        p:brand="福特" p:crop="北京" p:price="300000" p:speed="260">
    </bean>



</beans>

测试参考前面例子。

4.4 给bean赋值可以使用的值

4.4.1字面量:基本数据类型以及其封装类,String等类型都可以采用字面值注入的方式,

                       如果字面值中包含特殊字符,可以使用特定的语法<![CDATA[]]>把字面值包裹起来,编写简介。

xml:可以看到,如果出现特殊字符,可以使用转/义符代替特殊字符,但是代码不够简洁,使用特定语法就简洁很多。

    <bean id="book" class="com.wei.springDI.bean.Book">
        <property name="bookid" value="001"></property>
<!--        <property name="bookname" value="&lt;&lt;钢铁是怎样炼成的&gt;&gt;"></property>-->
        <property name="bookname">
            <value><![CDATA[钢铁是怎样炼成的]]></value>
        </property>
    </bean>

4.4.2 null值:如果不想给已有属性赋值可以使用<null/>标签为其赋

    <bean id="null" class="com.wei.springDI.bean.Person">
        <property name="id" value="103"></property>
        <property name="name" value="菲菲"></property>
        <property name="car"><null/></property>
    </bean>

4.4.3 给bean的级联属性赋值:调用其他bean的属性可以使用其id.属性来设置级联属性




    <!--引用其他的bean   ref -->
    <bean id="person" class="com.wei.springDI.bean.Person">
        <property name="id" value="101"></property>
        <property name="name" value="张三"></property>
        <property name="car" ref="car1"></property>

    <!-- 给级联属性赋值       -->
        <property name="car.speed" value="250"></property>
    </bean>

4.4.4 引用外部已声明的bean:调用ref,填写外部以及声明好的bean的id即可使用其属性

 <!--引用其他的bean   ref -->
    <bean id="person" class="com.wei.springDI.bean.Person">
        <property name="id" value="101"></property>
        <property name="name" value="张三"></property>
        <property name="car" ref="car1"></property>
    </bean>

4.4.5 内部bean:当bean实例仅仅给一个特定的属性使用时,可以将其声明为内部bean。内部bean声明直接包含在<property>或<constructor-arg>元素里,不需要设置任何id或name属性内部bean不能使用在任何其他地方。

  <!-- 内部bean   -->
    <bean id="person1" class="com.wei.springDI.bean.Person">
        <property name="id" value="102"></property>
        <property name="name" value="大力"></property>
        <property name="car">
            <!--    内部bean只能在内部使用        -->
            <bean class="com.wei.springDI.bean.Car">
                <property name="brand" value="保时捷"></property>
                <property name="crop" value="..."></property>
                <property name="price" value="2000000"></property>
                <property name="speed" value="500"></property>
            </bean>
        </property>
    </bean>

4.5 集合属性

在Spring中可以通过一组内置的XML标签来配置集合属性,例如:<list>,<set>或<map>。

4.5.1 List

实体类:

public class PersonList {
    private String name;
    private List<Car> cars;

    @Override
    public String toString() {
        return "PersonList{" +
                "name='" + name + '\'' +
                ", cars=" + cars +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Car> getCars() {
        return cars;
    }

    public void setCars(List<Car> cars) {
        this.cars = cars;
    }
}

xml:可以引用已创建的bean为list集合

    <!-- List集合   -->
    <bean id="personList" class="com.wei.springDI.bean.PersonList">
        <property name="name" value="wei"></property>
        <property name="cars">
            <list>
                <ref bean="car1"></ref>
                <ref bean="car2"></ref>
                <ref bean="car3"></ref>
            </list>
        </property>
    </bean>

4.5.2 Map:<map>标签里可以使用多个<entry>作为子标签。每个条目包含一个键和一个值。

    <!-- Map集合   -->
    <bean id="personMap" class="com.wei.springDI.bean.PersonMap">
        <property name="name" value="jerry"></property>
        <property name="cars">
            <map>
                <entry key="AA" value-ref="car2"></entry>
                <entry key="BB" value-ref="car3"></entry>
                <entry key="CC" value-ref="car1"></entry>
            </map>
        </property>
    </bean>

4.5.3 集合类型的bean:区别于内部bean,我们可以将集合bean的配置拿到外面,供其他bean引用。其他bean只需要利用ref:+集合bean的id即可引用集合bean内的数据。

    <!--集合bean-->
    <util:list id="listBean">
        <ref bean="car"></ref>
        <ref bean="car1"></ref>
        <ref bean="car3"></ref>
    </util:list>

引用集合bean

    <!-- List集合   -->
    <bean id="personList" class="com.wei.springDI.bean.PersonList">
        <property name="name" value="wei"></property>
        <property name="cars" ref="listBean">
            <list>
            </list>
        </property>
    </bean>

4.6 FactoryBean(工厂bean)

Spring中有两种类型的bean,一种是普通bean,另一种是工厂bean,即FactoryBean。工厂bean跟普通bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂bean的getObject方法所返回的对象。 

要想使用FactoryBean,必须实FactoryBean接口,并且实现他的三个未实现的方法。

public class CarFactoryBean implements FactoryBean<Car> {

    //工厂bean具体创建的bean对象是由getObject方法来返回的
    @Override
    public Car getObject() throws Exception {
        return new Car("五菱宏光","中国",200);
    }

    //返回具体的bean对象的类型
    @Override
    public Class<?> getObjectType() {
        return Car.class;
    }

    //bean可以是单例的 也可以是原型的(非单例)
    @Override
    public boolean isSingleton() {
        return true;
    }
}

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.xsd">


    <!--  通过FactoryBean 来配置bean
            FactoryBean具体返回的对象是由getObject方法来决定的
      -->
    <bean id="car" class="com.wei.factorybean.bean.CarFactoryBean"></bean>
</beans>

测试:

public class test {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-factorybean.xml");

        Car car = ctx.getBean("car", Car.class);
        System.out.println(car);
    }
}
发布了10 篇原创文章 · 获赞 1 · 访问量 362

猜你喜欢

转载自blog.csdn.net/qq_45648512/article/details/104097658