Spring 笔记二 :IOC与bean装配

Spring简介:

Spring是一个为简化企业应用级开发的简单框架。
它是轻量级的:Spring是非入侵的,基于Spring开发的对象可以不依赖于Spring的API。

Spring之HelloWorld

com.hust.HelloWorld

public class HelloWorld {
    private String name;

    public HelloWorld() {
        System.out.println("constrcutor...");
    }

    public void setNameNow(String name2) {
        System.out.println("setting");
        this.name = name2;
    }

    public void sayHello(){
        System.out.println("hello ,"+this.name);
    }
}

com.hust.Main

Spring提供了两种IOC容器的实现
-BeanFactory:IOC容器的基本实现。面向Spring本身
-Applicationcontext:是BeanFactory的子接口,提供了更高级的特性。面向开发者。
几乎所有的应用场合都直接使用ApplicationContext而非底层的BeanFactory.

public class Main {
    public static void main(String[] args) {
        //创建IOC容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContent.xml");
        //从IOC容器中获取bean实例
        HelloWorld hello =(HelloWorld) ac.getBean("helloWorld");
        hello.sayHello();
    }
}

Spring支持三种依赖注入的方式:

属性注入;
即通过setter方法注入Bean属性值或依赖对象。
构造器注入;
借助构造器注入初始化bean;借助< constructor-arg>元素
静态工厂方法注入;(很少使用,不推荐)

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

    <bean id="helloWorld" class="com.hust.HelloWorld" >
        <property name="nameNow" value="Spring"></property>
    </bean>

</beans>

IOC和DI
IOC(Inversion of Control):其思想是反转资源获取的方向。传统的资源查找要求组件向容器发起资源查找;作为回应,容器适时返回资源,应用了IOC之后,则是容器主动将资源推送给它所管理的组件,组件所要做的仅是选择一种适合的方式来接受资源。
DI(Dependency Injection)IOC 的另一种表述方式,即组件以一些预定义好的方式(例如setter方法)接受来自容器资源的注入。

没有IOC之前,我们是怎么办的呢?
1. 原始社会(很早很早以前):
这里写图片描述
2. 工厂设计模式
这里写图片描述
3. IOC控制反转:
这里写图片描述

注入属性值的细节

Spring中可以使用< list> < set> < map>来配置集合属性;
这些标签可以通过value指明常量值,ref指明bean引用,< /null>指定空元素,或者内嵌其它集合;
< map> 标签中可以用多个< entry>作为子标签,每个标签包含一个键和值;

<?xml version="1.0" encoding="UTF-8"?>
<!--suppress SpringModelInspection -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       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/util
        http://www.springframework.org/schema/util/spring-util-3.0.xsd
       ">

    <!--
    配置bean
    class:  bean的全类名,通过反射的方式在IOC中创建bean,所以一定要有无参数构造函数
    id:标识容器的bean,唯一性
    -->
    <!--属性注入使用property元素,为name指定bean的属性名称(具体以set方法后的字符为准)
    value是指定的属性值-->
    <bean id="helloWorld" class="com.hust.HelloWorld" >
        <property name="nameNow" value="Spring"></property>
    </bean>

    <!--通过构造方法配置bean属性 -->
    <bean id="car" class="com.hust.Car">
        <constructor-arg value="baoma" type="java.lang.String"></constructor-arg>
        <constructor-arg value="beijing" index="1"></constructor-arg>
        <constructor-arg value="1200000" type="double"></constructor-arg>
    </bean>

    <!--指定参数的位置和类型,区分重载的构造器 -->
    <bean id="car2" class="com.hust.Car">
        <constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
        <!--如果字面值含有特殊字符,可以使用<![CDATA[] ]> 包起来-->
        <constructor-arg  index="1"><value><![CDATA[Guangdong^]]></value></constructor-arg>
        <constructor-arg value="250" type="int"></constructor-arg>
    </bean>

    <bean id="person" class="com.hust.Person">
        <property name="name" value="Tom"></property>
        <property name="age" value="21"></property>
        <!--可以使用property 的ref属性建立bean之间的引用关系 -->
        <property name="car" ref="car"></property>
        <!--为级联属性赋值 -->

    </bean>

    <bean id="person2" class="com.hust.Person" p:age="23" p:name="Lisa">

        <!--内部bean ,不能被外部引用-->
        <property name="car" >
            <bean class="com.hust.Car">
                <constructor-arg name="brand" value="DAzhong"></constructor-arg>
                <constructor-arg name="corp" value="Zhejiang"></constructor-arg>
                <constructor-arg name="price" value="140000"></constructor-arg>
            </bean>
        </property>
    </bean>
    <bean id="person3" class="com.hust.Person">
        <constructor-arg  value="David"></constructor-arg>
        <constructor-arg  value="21"></constructor-arg>
        <constructor-arg  ref="car2"></constructor-arg>
        <!--为级联属性赋值 -->
        <property name="car.price" value="230000"></property>
    </bean>

    <util:list id="cars">
        <ref  bean="car"></ref>
        <ref bean="car2"></ref>
    </util:list>

    <bean id="person4" class="com.spring.Collection.Person">
        <property name="name" value="Xiong"></property>
        <property name="age" value="29"></property>
        <property name="car" ref="cars">



            <!--若想把list独立出来, 可以使用util命名空间(现在是在内部的) -->
        </property>
    </bean>

    <bean id="person5" class="com.spring.Collection.NewPerson">
        <property name="name" value="Rose"></property>
        <property name="age" value="23"></property>
        <property name="cars" >
           <map>
               <entry key="A" value-ref="car2"></entry>
               <entry key="B-" value-ref="car"></entry>
           </map>
        </property>
    </bean>
</beans>

xml中的自动装配

可以在xml中实现自动装配,需要做的仅是在< bean>的autowire属性中指定自动装配的模式;
byType: 根据类型(bean 里面的class属性)自动装配;若在xml中含有多个满足条件的bean,则会抛出异常
byName: 根据名称自动装配,必须将目标bean的id设置成属性名(set方法后面的第一个首字母变小写);

autowire.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"
       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">
<bean id="addressteo"  class="com.spring.Autowired.Address" p:city="Hangzhou" p:street="guanshan"></bean>
<bean id="carteo" class="com.spring.Autowired.Car" p:brand="Fute" p:price="321412"></bean>
    <bean id="car" class="com.spring.Autowired.Car" p:brand="Luhu" p:price="1380000"></bean>
    <bean id="xiangda" class="com.spring.Autowired.Person"
          p:name="Kitty" autowire="byName"></bean>
</beans>
Person类:
package com.spring.Autowired;

/**
 * Created by kaixin on 2018/8/21.
 */
public class Person {
    private String name;
    private Address address;
    private Car car;

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

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

    public void setAddressteo(Address address) {
        this.address = address;
    }

    public void setCarteo(Car car) {
        this.car = car;
    }
}

bean之间的关系:继承,依赖
(这里的继承指的是配置的继承,不是指那个extends)
被继承的bean我们叫它父bean,继承父bean的配置的bean我们叫它子bean。子bean可以覆盖父bean中的属性;父bean可以用abstract声明为抽象的bean,即不能被IOC容器实例化生成对象,只能被parent属性继承(作为模板)。
通过depend-on属性设置bean前置依赖的bean,这里只是保证了car先于person实例化,后于person销毁,person并没有把car作为自己的引用。

<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="address" class="com.spring.Autowired.Address"
          p:street="yuyuanlu" p:city="wuhan" abstract="true"></bean>
    <!--bean配置的继承,用parent属性指定继承哪个bean的配置-->
    <bean id="address2" parent="address" p:street="luoyulu"></bean>

    <bean id="car2" class="com.spring.Autowired.Car" p:brand="falali" p:price="20000000"></bean>
    <!--要求配置这个person时,必须有一个关联的car,即这个person依赖于car -->
    <bean id="person" class="com.spring.Autowired.Person"
          p:name="Wangsichong" p:addressteo-ref="address2" depends-on="car2" ></bean>
</beans>

Person{name='Wangsichong', address=Address{city='wuhan', street='luoyulu'}, car=null}

Spring容器中Bean的作用域

作用域一般指:这个对象的可见范围或可用域;
这里的作用域可以认为是bean定义与bean实例对象的关系。
通过scope属性来配置bean的作用域。
singleton:单例模式(默认值),在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例
prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例

SpEL

Spring表达式语言:使用#{ … }作为界定符
作用:

  • 通过id对bean进行引用
  • 调用方法以及引用bean对象的属性
  • 计算表达式、动态赋值

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

    <bean id="address" class="com.spring.spel.Address"
          p:street="sandianxilu" p:city="nanchang" ></bean>
    <bean id="car" class="com.spring.spel.Car" p:brand="tesila" p:price="230000">
        <!--调用静态方法或静态属性,在spel中用T() ,它返回一个Class.Object,再调用静态方法或属性-->
        <property name="typrperimeter" value="#{T(java.lang.Math).PI *80}"></property>
    </bean>
    <bean id="person" class="com.spring.spel.Person" p:name="casual" >
        <!--用spel引用其它的bean -->
        <property name="carteo" value="#{car}"></property>
        <!--用spel应用其它bean的属性 -->
        <property name="city" value="#{address.city}"></property>
        <!-- 使用spel运算符 来动态赋值-->
        <property name="info" value="#{car.price>=300000 ? 'super_VIP':'VIP' }"></property>
    </bean>

</beans>

Person类

public class Person {
    private String name;

    private Car car;

    private String city;

    //汽车的价格大于300000的话,info为super_VIP
    //否则为VIP
    private String info;

    public String getName() {
        return name;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

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

    public void setCarteo(Car car) {
        this.car = car;
    }

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

    public Car getCar() {
        return car;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值