Java学习记录 Spring核心loC

Spring IoC容器

Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想

Ioc 在开发中,无需自行实例对象,而是有 Spring Ioc容器 创建。Spring容器会负责控制程序之间的关系,而不是由代码直接控制,因此,控制权由 Spring容器 接管,控制权发生了反转,是Ioc设计思想

Spring 提供了两种 IoC 容器,分别为 BeanFactory 和 ApplicationContext.

BeanFactory

BeanFactory是一个管理Bean的工厂,根据xml配置文件中的定义Bean进行管理,主要负责初始化各种Bean,并调用他们的生命周期方法

加载xml配置文件,如下所示:(xml文件必须是绝对路径)

BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("D:\applicationContext.xml"));

ApplicationContext

ApplicationContext 是 BeanFactory 的子接口,也是 应用上下文。BeanFactory 的所有功能,还添加了对 i18n(国际化)、资源访问、事件传播等方面的良好支持

ApplicationContext 接口有两个常用的实现类

ClassPathXmlApplicationContext

该类从类路径 ClassPath 中寻找指定的 XML 配置文件,找到指定xml文件加载实例化工作,如下所示

ApplicationContext applicationContext = new ClassPathXmlApplicationContext(Spring配
置文件的名称);

FileSystemXmlApplicationContext

该类从指定系统路径的文件 进行寻找指定 XML 配置文件,找到指定xml文件加载实例化工作,如下所示

ApplicationContext applicationContext = new FileSystemXmlApplicationContext(Spring配
置文件的路径和名称);

在读取 Spring 的配置文件时,FileSystemXmlApplicationContext 是通过参数指定配置文件的位置,它可以获取类路径之外的资源

Bean标签

XML 格式配置文件的根元素是 <beans>,该元素包含了多个 <bean> 子元素,每一个 <bean> 子元素定义了一个 Bean,并描述了该 Bean 如何被装配到 Spring 容器中。

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

    <!-- 使用id属性定义person1,其对应的实现类为com.mengma.person1 (类路径及包路径)-->
    <bean id="person1" class="com.mengma.person1 " />
    <!--使用name属性定义person2,其对应的实现类为com.mengma.domain.Person2 (类路径及包路径) -->
    <bean name="Person2" class="com.mengma.domain.Person2"/>
        
</beans>

bean属性

属性名称描述
id是一个 Bean 的唯一标识符,Spring 容器对 Bean 的配置和管理都通过该属性完成
nameSpring 容器同样可以通过此属性对容器中的 Bean 进行配置和管理,name 属性中可以为 Bean 指定多个名称,每个名称之间用逗号或分号隔开
class该属性指定了 Bean 的具体实现类,它必须是一个完整的类名,使用类的全限定名
scope用于设定 Bean 实例的作用域,其属性值有 singleton(单例)、prototype(原型)、request、session 和 global Session。其默认值是 singleton
lazy-init延迟加载(true/false 默认false)。通过getbean()方法获取对象时才会生效
init-method初始化对象方法
destroy-method销毁对象方法
list用于封装 List 或数组类型的依赖注入
set用于封装 Set 类型属性的依赖注入
map用于封装 Map 类型属性的依赖注入

实例Bean

实例Bean有三种方式,构造器实例化、静态工厂方式实例化、实例工厂方式实例化

  1. 创建实体对象

    项目 src目录 下 com.People

    package com;
    
    public class People {
        int id;
        String name;
        
        public People() {
            System.out.println("无参实例");
        }
        public People(int id , String name) {
            System.out.println("有参实例");
            this.id = id;
            this.name = name;
        }
        
        @Override
        public String toString() {
            return "People{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
    
    
  2. 创建工厂
    项目 src目录 下 com.MyFactory

    package com;
    
    public class MyFactory {
        
        public MyFactory() {
            System.out.println("MyFactory--构造!");
        }
        
        /**
         * 实例方法
         */
        public People instanceFun(){
            System.out.println("MyFactory---instanceFun");
            return new People(001,"成龙");
        }
        
        /**
         * 静态方法
         */
        public static People staticFun(){
            System.out.println("MyFactory---staticFun");
            return new People(002, "李小龙");
        }
        
    }
    
  3. 创建 Spring配置文件
    如果是 Maven项目 ,就放在 resources 下;不是则 自定义位置

    <?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="test01" class="com.People" lazy-init="true"/>
    <!--    有参构造-->
        <bean id="test02" class="com.People" lazy-init="true">
            <constructor-arg name="id" value="001"/>
            <constructor-arg name="name" value="嘿嘿嘿"/>
        </bean>
        <bean id="test03" class="com.People" lazy-init="true">
            <constructor-arg index="0" value="002"/>
            <constructor-arg index="1" value="啦啦啦"/>
        </bean>
    <!--    工厂方法-->
        <bean id="test04" class="com.MyFactory" lazy-init="true"/>
        <bean id="test05" factory-bean="test04" factory-method="instanceFun" lazy-init="true"/>
    <!--    工厂方法(静态)-->
        <bean id="test06" class="com.MyFactory" factory-method="staticFun" lazy-init="true"/>
    </beans>
    
  4. 创建测试类
    前提需要引入依赖

    package com;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
        
        String createType = "createType.xml";
        
        @Test
        public void test01(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext(createType);
            People test01 = (People) applicationContext.getBean("test01");
            People test02 = (People) applicationContext.getBean("test02");
            People test03 = (People) applicationContext.getBean("test03");
            People test05 = (People) applicationContext.getBean("test05");
            People test06 = (People) applicationContext.getBean("test06");
            System.out.println("============");
            System.out.println("test01 : " + test01);
            System.out.println("test02 : " + test02);
            System.out.println("test03 : " + test03);
            System.out.println("test05 : " + test05);
            System.out.println("test06 : " + test06);
        }
        
    }
    
  5. 结果查看
    使用 JUnit 测试运行

    无参实例
    有参实例
    有参实例
    MyFactory--构造!
    MyFactory---instanceFun
    有参实例
    MyFactory---staticFun
    有参实例
    ============
    test01 : People{id=0, name='null'}
    test02 : People{id=1, name='嘿嘿嘿'}
    test03 : People{id=2, name='啦啦啦'}
    test05 : People{id=1, name='成龙'}
    test06 : People{id=2, name='李小龙'}
    

依赖注入 DI

DI—Dependency Injection,即“依赖注入”。需要通过 简单的配置,而无需任何代码就可指定目标需要的资源

Ioc和DI是同一个概念的不同角度描述。IoC是一种思想;DI是实现它的手段。Spring框架使用依 赖注入实现IoC

子元素名称及属性父元素名称说明
constructor-argbean可以使用此元素传入构造参数进行实例化。该元素的 index 属性指定构造参数的序号(从 0 开始),type 属性指定构造参数的类型
propertybean用于调用 Bean 实例中的 Set 方法完成属性赋值,从而完成依赖注入。该元素的 name 属性指定 Bean 实例中的相应属性名
entrymap用于设置一个键值对。其 key 属性指定字符串类型的键值,ref 或 value 子元素指定其值
属性说明
refproperty、constructor-arg、…该元素中的 bean 属性用于指定对 Bean 工厂中某个 Bean 实例的引用
valueproperty、constructor-arg、…用于直接指定一个常量值
autowirebyName/byType根据 Property 特征进行自动装配 name 或 Type 进行自动装配

注入分类

set注入

通过 set 方法传入被调用者的实例。这种注入方式简单、直观,因而在 Spring 的依赖注入中大量使用

public class TeamService {
    
    //注入测试
    private TeamDao teamDao;
    
   ···
    
    //set注入 (实现TeamDao对象实例)
    public void setTeamDao(TeamDao teamDao) {
        this.teamDao = teamDao;
    }
    ···
}

构造器注入

在构造调用者实例的同时,完成被调用者的实例化。使用构造器设置依赖关系

public class TeamService {
    
    //注入测试
    private TeamDao teamDao;
    
    public TeamService() {}
    //构造器注入
    public TeamService(TeamDao teamDao) {
        this.teamDao = teamDao;
    }
    ···
}

自动注入

可通过 bean标签 设置 autowire 属性值,为引用类型属性进行隐式自动注入(默认是不自动注入引用类型属性)。根据 自动注入判断标准的不同。可以分为两种:

byName:根据名称自动注入
byType: 根据类型自动注入

byName

前提条件:xml配置文件中 bean标签属性 idname 值 与 调用者类中的属性名 相同,可使用byName方式自动注入依赖实例

.xml配置文件:

	<!--id 属性值指定名称-->
	<bean id="teamDao" class="com.dao.TeamDao"/>
<!--    自动注入-->
    <!--以Name为注入准则-->
    <bean id="teamService" class="com.service.TeamService" autowire="byName"/>

调用者TeamService类:

public class TeamService {
    
    //注入测试 (属性名相同 teamDao )
    private TeamDao teamDao;
    
    ···
}

byType

前提条件:xml配置文件中 bean标签属性 class值 属性指定的类 与 调用者类中的属性类型相同,可使用byType自动注入依赖实例

.xml配置文件:

	<!--class 属性值指定类-->
	<bean id="teamDao" class="com.dao.TeamDao"/>
<!--    自动注入-->
    <!--以Name为注入准则-->
    <bean id="teamService" class="com.service.TeamService" autowire="byType"/>

调用者TeamService类:

public class TeamService {
    
    //注入测试 (属性类型相同 TeamDao )
    private TeamDao teamDao;
    
    ···
}

注解装配Bean

在 Spring 中,尽管使用 XML 配置文件可实现 Bean 的装配工作,如果应用中 Bean 的数量较多,会导致 XML 配置文件过于臃肿,从而给维护和升级带来一定的困难,因此 Spring 提供了注解应用,需要在原有的运行环境基础上做些变化,由此减少过多的Bean

@Component

在类上添加上 @Component注解 表示该类实例的对象的权限交给 Spring容器 。注解的value属性用于指定bean的 id值 或 name值 ,但一般情况可省略 value 属性!(该注解指定id是类名的首字母小写)

以下注解与 @Component注解 用法和功能 相同,表达的含义不同!

  • @Repository
    dao层实现类的注解(持久层)
  • @Service
    service层实现类的注解(业务层)
  • @Controller
    controller层实现类的注解(控制层)

@Value

该 注解 是为指定属性 注入值。该注解用在 类的属性 或 指定set方法上 。
其注解注入 原理 和 set方法 写入是一样,因此 set方法 也可

package com;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class MyUser {
    //方式1
    @Value("001")
    private int id;
    @Value("张三")
    private String name;
    @Value("23")
    private int age;
    @Value("洛杉矶")
    private String locateion;
    
    ···
    
    //方式2
    @Value("001")
    public void setId(int id) {
        this.id = id;
    }
    @Value("张三")
    public void setName(String name) {
        this.name = name;
    }
    @Value("23")
    public void setAge(int age) {
        this.age = age;
    }
    @Value("洛杉矶")
    public void setLocateion(String locateion) {
        this.locateion = locateion;
    }
    
   	···
}

包扫描

需要在 xml配置文件中配置组件扫描器,用于在指定包中扫描的注解。如果未添加扫描,则对象添加的注解 将无法实例化

xml配置文件 添加扫描

  1. beans标签 配置属性
    xmlns:context属性: xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation属性(添加值):
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd

    ···
    <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"
           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.xsd">
    	···
    </beans>
    
  2. context:component-scan标签 指定包扫描
    分隔符可以使用逗号(,)分号(;)还可以使用空格,不建议使用空格。

    <?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"
        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.xsd">
    <!--    包扫描 方法1: (包路径 Annotation.dao、Annotation.service、Annotation.controller)-->
    	    <context:component-scan base-package="Annotation.dao"/>
    	    <context:component-scan base-package="Annotation.service"/>
    	    <context:component-scan base-package="Annotation.controller"/>
    <!--    包扫描 方法2: (包路径 Annotation.dao、Annotation.service、Annotation.controller)-->
    	    <context:component-scan base-package="Annotation.dao;Annotation.service;Annotation.dao"/>
    </beans>
    
  3. 添加对应注解即可

自动注入

自动注入指定对象的前提,需要为该对象添加注解,且 上级包 或 指定类 有扫描到!

@Autowired

用于对 Bean 的 属性变量、属性Set方法 及构造方法进行标注(构造方法应用的前提,参数必须指定的是对应的实例对象),配合对应的注解处理器完成 Bean 的自动配置工作。默认按照 Bean 的类型 进行装配

@Autowired 还有一个属性 required,默认值为 true,表示匹配失败后终止程序运行;若值为 false,则匹配失败后 其属性值为 null

@Qualifier

与 @Autowired 注解配合使用,会将默认的按 Bean类型 装配修改为按 Bean实例队形名称 装配,Bean 的实例名称由 @Qualifier 注解的 value参数 指定

@Resource

该注解 在jdk1.6版本以上 支持使用,Bean属性可指定按照 类型(type) 或 名称(name) 进行自动注入,可在 属性变量、属性Set方法 进行使用


版权声明:本文为weixin_45963193原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。