Spring IoC

Spring Ioc是Spring公司对“控制反转”思想的实现,运用xml来管理和创建bean

三种XML管理、创建bean的方式:

  1. 基于构造方法实例对象。

  2. 基于静态工厂实例化对象。

  3. 基于工厂实例方法实例化对象。

实体类

package pers.thc.spring.IoC.entity;

public class Apple {
    private String title;
    private String color;
    private String origin;

    public Apple(){}
    public Apple(String title, String color, String origin) {
        this.title = title;
        this.color = color;
        this.origin = origin;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getOrigin() {
        return origin;
    }

    public void setOrigin(String origin) {
        this.origin = origin;
    }

    @Override
    public String toString() {
        return "Apple{" +
                "title='" + title + '\'' +
                ", color='" + color + '\'' +
                ", origin='" + origin + '\'' +
                '}';
    }
}
package pers.thc.spring.IoC.entity;

public class Child {
    private String name;
    private Apple apple;
    public Child(){}

    public Child(String name, Apple apple) {
        this.name = name;
        this.apple = apple;
    }

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

    public String getName() {
        return name;
    }

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

    public Apple getApple() {
        return apple;
    }

    public void setApple(Apple apple) {
        this.apple = apple;
    }
}

静态工厂类

package pers.thc.spring.IoC.factory;

import pers.thc.spring.IoC.entity.Apple;

public class AppleFactory {
    public static Apple createSweetApple(){
        Apple apple = new Apple("红富士", "深红", "欧洲");
        return apple;
    }
}

实例工厂类

package pers.thc.spring.IoC.factory;

import pers.thc.spring.IoC.entity.Apple;

public class AppleFactoryInstance {
    public Apple createSweetApple(){
        Apple apple = new Apple("红富士", "深红", "欧洲");
        return apple;
    }
}

applicationContext.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="sweetApple" class="pers.thc.spring.IoC.entity.Apple">
        <property name="title" value="红富士"/>
        <property name="color" value="深红"/>
        <property name="origin" value="欧洲"/>
    </bean>
    <bean id="sourApple" class="pers.thc.spring.IoC.entity.Apple">
        <property name="origin" value="中亚"/>
        <property name="color" value="青色"/>
        <property name="title" value="青苹果"/>
    </bean>
    <bean id="softApple" class="pers.thc.spring.IoC.entity.Apple">
        <property name="title" value="金帅"/>
        <property name="color" value="金色"/>
        <property name="origin" value="中国"/>
    </bean>
    <bean class="pers.thc.spring.IoC.entity.Apple">
        <property name="title" value="苹果"/>
        <property name="color" value="未知"/>
        <property name="origin" value="位置"/>
    </bean>
    <bean name="Lily,lily" class="pers.thc.spring.IoC.entity.Child">
        <property name="apple" ref="sweetApple"/>
        <property name="name" value="Lily"/>
    </bean>
    <bean id="apple1" class="pers.thc.spring.IoC.entity.Apple">
        <constructor-arg name="title" value="红富士"/>
        <constructor-arg name="color" value="深红"/>
        <constructor-arg name="origin" value="欧洲"/>
    </bean>
    <bean id="apple2" class="pers.thc.spring.IoC.entity.Apple">
        <constructor-arg index="0" value="红富士"/>
        <constructor-arg index="1" value="深红"/>
        <constructor-arg index="2" value="欧洲"/>
    </bean>
    <!--采用静态工厂的形式创建apple实例-->
    <bean id="apple3" class="pers.thc.spring.IoC.factory.AppleFactory" factory-method="createSweetApple"/>
    <!--采用工厂实例的形式创建apple实例-->
    <bean id="appleFactoryInstance" class="pers.thc.spring.IoC.factory.AppleFactoryInstance"/>
    <bean id="apple4" factory-bean="appleFactoryInstance" factory-method="createSweetApple"/>
</beans>
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="sweetApple" class="pers.thc.spring.IoC.entity.Apple">
        <property name="title" value="富士"/>
        <property name="color" value="深红"/>
        <property name="origin" value="日本"/>
    </bean>
</beans>

Application类

package pers.thc.spring.IoC;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import pers.thc.spring.IoC.entity.Apple;
import pers.thc.spring.IoC.entity.Child;

public class SpringApplication {
    public static void main(String[] args) {
        String configLocations[]=new String[]{
            "classpath:applicationContext.xml", "classpath:applicationContext1.xml"};
        //应用上下文加载顺序与字符串先后顺序有关
        //启动IoC容器
//        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
        //利用getBean来获取相应的实例对象
//        Apple sweetApple = (Apple)context.getBean("sweetApple");
        Apple sweetApple = context.getBean("sweetApple", Apple.class);//由于sweetApple在两个配置文件中都有,故后加载的配置文件中的sweetApple会覆盖掉先加载配置文件中的sweetApple

        Child Lily = context.getBean("Lily", Child.class);
        Child lily = context.getBean("lily", Child.class);//通过name标签可以设置多个bean标识,此处用lily标识获取实例对象

        Apple apple = context.getBean("pers.thc.spring.IoC.entity.Apple", Apple.class);//若bean没有id、name标签,则通过完整类名获取实例对象

        Apple apple1 = context.getBean("apple1", Apple.class);
        Apple apple2 = context.getBean("apple2", Apple.class);
        Apple apple3 = context.getBean("apple3", Apple.class);
        Apple apple4 = context.getBean("apple4", Apple.class);

        System.out.println(sweetApple);
        System.out.println(Lily);
        System.out.println(lily);
        System.out.println(apple);
        System.out.println(apple1);
        System.out.println(apple2);
        System.out.println(apple3);
        System.out.println(apple4);

    }
}

路径表达式:

  1. classpath:config.xml 扫描classpath根路径(不包含jar)的config.xml

  2. classpath:pers/thc/config.xml 扫描classpath下(不包含jar)pers.thc包中的config.xml

  3. classpath*:pers/thc/config.xml 扫描classpath下(包含jar)pers.thc包中的config.xml

  4. classpath:config-*.xml 扫描classpath根路径下所有一config-开头的XML文件

  5. classpath:pers/**/config.xml 扫描pers包下(包含任何子包)的config.xml file:c/:config.xml 扫描c盘根路径config.xml

两种对象依赖注入方式:

  1. setter注入对象(property)

  2. 构造方法注入对象(constructor-arg)

IoC模拟团队分工:

        bookshop 利用不同的配置文件,约定好bean的id,建立依赖关系(service的parent context为dao),实现分工合作。 其次,利用IoC容器还可以实现对象之间的解耦,当dao层修改实现细节时,秩序保证bean的id不变,service层不需要进行任何改变。

注入集合对象:

        通过“公司资产配置清单”案例学习集合类型动态注入

公司实体类

package pers.thc.spring.IoC.companyProperties.entity;

import java.util.List;
import java.util.Map;
import java.util.Properties;

public class Company {
    private List<String> rooms;
    private Map<String,Computer> computers;
    private Properties info;

    @Override
    public String toString() {
        return "Company{" +
                "rooms=" + rooms +
                ", computers=" + computers +
                ", info=" + info +
                '}';
    }

    public List<String> getRooms() {
        return rooms;
    }

    public void setRooms(List<String> rooms) {
        this.rooms = rooms;
    }

    public Map<String, Computer> getComputers() {
        return computers;
    }

    public void setComputers(Map<String, Computer> computers) {
        this.computers = computers;
    }

    public Properties getInfo() {
        return info;
    }

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

电脑实体类

package pers.thc.spring.IoC.companyProperties.entity;

public class Computer {
    private String brand;
    private String type;
    private String sn;
    private Float price;

    public Computer() {
    }

    public Computer(String brand, String type, String sn, Float price) {
        this.brand = brand;
        this.type = type;
        this.sn = sn;
        this.price = price;
    }

    @Override
    public String toString() {
        return "Computer{" +
                "brand='" + brand + '\'' +
                ", type='" + type + '\'' +
                ", sn='" + sn + '\'' +
                ", price=" + price +
                '}';
    }

    public String getBrand() {
        return brand;
    }

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

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getSn() {
        return sn;
    }

    public void setSn(String sn) {
        this.sn = sn;
    }

    public Float getPrice() {
        return price;
    }

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

applicationContext.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="c1" class="pers.thc.spring.IoC.companyProperties.entity.Computer">
        <constructor-arg name="brand" value="华硕"/>
        <constructor-arg name="type" value="笔记本电脑"/>
        <constructor-arg name="sn" value="18977240383"/>
        <constructor-arg name="price" value="9880.0"/>
    </bean>
    <bean class="pers.thc.spring.IoC.companyProperties.entity.Computer">
        <constructor-arg name="brand" value="华硕"/>
        <constructor-arg name="type" value="笔记本电脑"/>
        <constructor-arg name="sn" value="8943464678"/>
        <constructor-arg name="price" value="9880.0"/>
    </bean>
    <bean class="pers.thc.spring.IoC.companyProperties.entity.Computer">
        <constructor-arg name="brand" value="微星"/>
        <constructor-arg name="type" value="笔记本电脑"/>
        <constructor-arg name="sn" value="4964613786"/>
        <constructor-arg name="price" value="9880.0"/>
    </bean>
    <bean id="company" class="pers.thc.spring.IoC.companyProperties.entity.Company">
        <property name="rooms">
            <list>
                <value>2001-总裁办</value>
                <value>2003-总经理办公室</value>
                <value>2010-研发部会议室</value>
            </list>
        </property>
        <property name="computers">
            <map>
                <entry key="dev-88172" value-ref="c1"/>
                <entry key="dev-88173">
                    <bean class="pers.thc.spring.IoC.companyProperties.entity.Computer">
                        <constructor-arg name="brand" value="华硕"/>
                        <constructor-arg name="type" value="笔记本电脑"/>
                        <constructor-arg name="sn" value="18977240384"/>
                        <constructor-arg name="price" value="9880.0"/>
                    </bean>
                </entry>
                <entry key="dev-88174">
                    <bean class="pers.thc.spring.IoC.companyProperties.entity.Computer">
                        <constructor-arg name="brand" value="联想"/>
                        <constructor-arg name="type" value="台式机"/>
                        <constructor-arg name="sn" value="18977240385"/>
                        <constructor-arg name="price" value="19880.0"/>
                    </bean>
                </entry>
            </map>
        </property>
        <property name="info">
            <props>
                <prop key="phone">0772-3626316</prop>
                <prop key="address">广西省柳州市城中区八一路XX路XX栋XXXX室</prop>
                <prop key="website">http://www.xxx.com</prop>
            </props>
        </property>
    </bean>
</beans>

Application类

package pers.thc.spring.IoC.companyProperties;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import pers.thc.spring.IoC.companyProperties.entity.Company;
import pers.thc.spring.IoC.companyProperties.entity.Computer;

public class CompanyPropertiesApplication {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext-company-properties.xml");
        Company company = context.getBean("company", Company.class);
        System.out.println(company);
        //获取容器内所有beanId数组
        String[] names = context.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
        Computer computer = context.getBean("pers.thc.spring.IoC.companyProperties.entity.Computer#1", Computer.class);
        System.out.println(computer);//获取匿名bean的方法-2,通过类名全称#序号来获取相应的bean对象。序号为0,1,2……,按applicationContext.xml中的顺序递推
    }
}

bean scope属性:

  1. bean scope属性用于决定对象何时被创建与作用范围

  2. bean scope配置将影响容器内对象的数量

  3. 默认情况下bean会在IoC容器创建后自动实例化,全局唯一

bean scope属性清单:

  1. singleton 单例(默认值),每一个容器有且只有唯一的实例,实例会被全局共享。单例多线程,但存在线程安全风险。 singleton线程安全问题,a=2(用户1)a.setNum(1)->a对象num=1,(用户2)sout(a.getNum())->本应输出2,现输出1

  2. prototype 多例,每次使用时都会创建一个实例

  3. request web环境下,每一次独立请求存在唯一实例

  4. session web环境下,每一次session存在有唯一实例

  5. global session portlet的web应用的共享session中

  6. websocket 每一次websocket连接中存在唯一实例

singleton(左)和prototype(右)对比:

  1. 对象数量:全局唯一 存在多个

  2. 实例化时机:IoC容器启动时 getBean()或对象注入时

  3. 线程安全问题: 存在 不存在

  4. 执行效率:高 低

bean的生命周期:

  1. 容器行为:Ioc容器准备初始化解析XML->为对象注入属性->IoC容器初始化完毕->IoC容器准备销毁

  2. 对象行为:对象实例化执行构造方法->调用init-method初始化方法->执行业务逻辑->调用destroy-method释放资源

Order实体类

package pers.thc.spring.IoC.lifecycle;

public class Order {
    private Float price;
    private Integer quantity;
    private Float total;

    public Order(){
        System.out.println("创建Order对象,"+this);
    }
    public void init(){
        System.out.println("执行init()方法");
        total=price*quantity;
    }
    public void destroy(){
        System.out.println("释放与订单对象相关的资源");
    }
    public void pay(){
        System.out.println("订单金额为:"+total);
    }
    public Float getPrice() {
        return price;
    }

    public void setPrice(Float price) {
        System.out.println("设置price:"+price);
        this.price = price;
    }

    public Integer getQuantity() {
        return quantity;
    }

    public void setQuantity(Integer quantity) {
        System.out.println("设置quantity:"+quantity);
        this.quantity = quantity;
    }

    public Float getTotal() {
        return total;
    }

    public void setTotal(Float total) {
        this.total = total;
    }
}

application Context.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="order1" class="pers.thc.spring.IoC.lifecycle.Order" init-method="init" destroy-method="destroy">
        <property name="price" value="23.0"/>
        <property name="quantity" value="10"/>
    </bean>
</beans>

Application类

package pers.thc.spring.IoC.lifecycle;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LifeCycleApplication {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext-lifecycle.xml");
        System.out.println("========IoC容器已初始化========");
        Order order1 = context.getBean("order1", Order.class);
        order1.pay();
        context.registerShutdownHook();//调用destroy-method方法销毁bean实例
    }
}

注解开发: 三类注解

  1. 组件装配注解-声明当前类的功能和职责 四类组件类型注解:

    1. @Component 组件注解,通用注解,被注解描述的类将被IoC容器管理并实例化

    2. @Controller 语义注解,MVC控制层

    3. @Service 语义注解,MVC业务层

    4. @Repository 语义注解,MVC数据持久化层 开启组件扫描: <context:component-scan package="pers.thc"> <context:exclude-filter type="regex" expression="pers.thc.exl*"/> /context:component-sacn

  2. 自动装配注解-根据属性特征自动注入对象 两类自动装配注解:

    1. 按类型装配:

      1. @Autowired 按容器内对象类型动态诸如属性,由Spring机构提供

      2. @Inject 基于JSR-330(Denpendency Inject for java)标准,其他同@Autowired,但不支持required属性

    2. 按名称装配:

      1. @Named 与@Inject配合使用,JSR-330标准,按属性名自动装配属性

      2. @Resource 基于JSR-250规范,优先按名称、再按类型智能匹配

  3. 元数据注解-更细化的辅助IoC容器管理对象的注解

    1. @Primary 按类型装配时出现多个相同类型对象,拥有此注解对象优先被注入

    2. @PostConstruct 描述方法,相当于XML中init-method配置的注解版本

    3. @PreDestroy 描述方法,相当于XML中destroy-method配置的注解版本

    4. @Scope 设置对象的scope属性

    5. @Value 为属性注入静态数据

使用Java Config配置IoC容器: Java Config核心注解

  1. @Configuration 描述类,说明当前类时Java Config配置类,完全替代XML文件

  2. @Bean 描述方法,方法返回对象将被IoC容器管理,beanId默认为方法名

  3. @ImportResource 描述类,加载静态文件,可以使用@Value注解获取

  4. @ComponentScan 描述类,同XML的context:component-scan标签

Spring与JUnit4整合

  1. Maven工程依赖spring-test

  2. 利用@RunWith(让Spring接管JUnit4的控制权)与@ContextConfiguration(初始化过程中加载哪个初始化文件)描述测试用例类

  3. 测试用例类从容器获取对象完成测试用例的执行

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import pers.thc.spring.IoC.springtest.service.UserService;

import javax.annotation.Resource;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-test.xml"})
public class SpringTestor {
    @Resource
    private UserService userService;

    @Test
    public void testUserService(){
        userService.createUser();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值