Spring FramWork Documentation 5.2.0 基于Idea实践学习IoC

本文详细介绍了Spring Framework 5.2.0中IoC(控制反转)的概念及其实践,包括IoC的创建对象方式、Spring配置、依赖注入实现、自动装配以及注解开发。特别强调了使用Java配置类@Configuration来实现IoC配置,降低了代码耦合度,简化了对象管理。
摘要由CSDN通过智能技术生成

官网

Documentation
搭配工程文件学习测试

Spring是一个轻量级的控制反转(IoC)和面向切面编程(AOP)的框架

以下是对IoC内容的实践与理解

首先,什么是IoC?

名词解释

IoC is also known as dependency injection (DI).

IoC——Inversion of control. (控制反转)

DI——Dependency Injection(依赖注入)

IoC特点

  • 控制权由程序代码转移到了外部容器
  • 由容器动态地将某种依赖关系注入到组件之中
  • 组件之间的依赖关系由容器在运行期决定

正常业务逻辑

正常业务逻辑如下

  1. UserDao接口

  2. UserDaoImpl实现类(实现类就是实现接口)

  3. UserService 业务接口

  4. UserServiceImpl 业务实现类

Q:这个时候业务层怎么调用Dao层?

A:业务层调用业务实现类去获取数据层

  • ServiceImpl

    public class UserServiceImpl implements UserService{
        
        private UserDao userDao = new  UserDaoImpl();
        
        public void getUser(){
            userDao.getUser();
        }
    }
    
  • Test

    public class Test{
        public static void main(String[] args){
            
            //用户只接触业务层
            UserService userService = new UserServiceImpl();
            userService.getUser();
        }
    }
    

Q:但是当增加一个新的Dao层实现方法,并且用户想调用,怎么实现?

A:新的dao层的方法是一个新的类,只能在业务处理类有调用到实现方法的时候修改

  • UserDapMySqlImpl

    public class UserDapMySqlImpl implements UserDao{
        public void getUser(){
            System.out.pritnln("新的方法");
        }
    }
    
  • ServiceImpl(此处调用,此处修改)

    public class UserServiceImpl implements UserService{
        
        private UserDao userDao = new  UserDapMySqlImpl(); //这里修改
        
        public void getUser(){
            userDao.getUser();
        }
    }
    

Q:每增加一个新的Dao方法,都要修改业务层实现方法,怎么不修改?

A:利用set方法进行动态实现值的注入

  • ServiceImpl
public class UserServiceImpl implements UserService{
    
    private UserDao userDao;
    
    //利用set进行动态实现值的注入
    public void setUserDao(UserDao userDao){
        this.userDao = userDao;
    }
    
    public void getUser(){
        userDao.getUser();
    }
}
  • Test
public class Test{
    public static void main(String[] args){
        
        //用户只接触业务层
        UserService userService = new UserServiceImpl();
        
        //随心调用
        ((UserServiceImpl)userService).setUserDao(new UserDapMySqlImpl);
        ((UserServiceImpl)userService).setUserDao(new UserDapImpl);
      
        userService.getUser();
    }
}

以上。正常的业务逻辑中,程序是主动创建对象,控制权在程序猿手中;而使用set方法之后,程序不再具有主动性,而是变成了被动的接收对象,主动权在用户手中。不再去管理对象的创建,耦合性大大降低,专注业务实现。

控制反转是什么?

IoC,是一种设计思想,而DI是实现IoC的一种方法。没有IoC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序猿自己控制。控制反转则将对象的创建转移给第三方,也就是获得依赖对象的方式反转了。
在这里插入图片描述

Spring容器初始化

Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从IoC容器中取出需要的对象。

在这里插入图片描述

配置Bean

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的。

而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。


以上,控制反转是一种通过描述(XML或注解) 并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。

1、IoC创建对象的方式

(Bean被创建的调用方式)也就是 Bean注入

加载完XML就已经把所有对象创建了

1)、使用无参构造
 <!--无参构造,普通注入-->
    <bean id="user" class="com.suren.pojo.User">
        <property name="name" value="素人"/>
    </bean>
2)、有参构造函数
  • 下标

    <!--有参构造 下标赋值-->
        <bean id="user" class="com.suren.pojo.User">
            <constructor-arg index="0" value="素人"/>
        </bean>
    
  • 类型

    <!--有参构造 类型 不建议使用-->
        <bean id="user" class="com.suren.pojo.User">
            <constructor-arg type="java.lang.String" value="素人"/>
        </bean>
    
  • 参数名

    <!--直接通过参数名-->
        <bean id="user" class="com.suren.pojo.User">-->
            <constructor-arg name="name" value="素人"/>
        </bean>
    

2、Spring配置

1)、别名
<alias name="user" alias="user2"/>
2)、Bean的配置
id : bean的唯一标识符,相当于变量名
class :bean对象所对应的全限定名:包名+类 
name : 也是别名,可以用来获取
3)、 import

在applicationContext里包含以下,就能导入这些bean文件

<import resource="bean1.xml"/>
<import resource="bean2.xml"/>

3、依赖注入实现

1)、构造器注入(Bean注入

IoC创建对象,如上述


2)、 Set方式注入(推荐)
  • 依赖注入:Set注入,为每个属性提供setter方法,对应属性
    • 依赖:bean对象的创建依赖于容器
    • 注入:bean对象的所有属性,由容器来注入
  • 集合类型的属性注入

    Spring 对每个常用集合对象,提供单独元素完成注入

    • List 对象 ---- 元素
    • Set 对象 ---- 元素
    • Map对象 ----元素
    • Properties 对象 ---- 元素

    (map和properties是{}输出)

3)、拓展方式注入
  • P空间 – properties —对应Set方法

    将 子元素,简化为元素属性配置

     xmlns:p="http://www.springframework.org/schema/p"
     <bean id="" class="" p:xx=""/>
    
  • C空间 —对应构造器方法

    xmlns:c="http://www.springframework.org/schema/c"
    <bean id="" class="" c:xx=""/>
    

4、bean的自动装配

作用域

ScopeDescription
singleton(Default) Scopes a single bean definition to a single object instance for each Spring IoC container.
prototypeScopes a single bean definition to any number of object instances.
requestScopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
sessionScopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
applicationScopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.
websocketScopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.
  1. 单例模式 singleton

    <bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
    
  2. 原型模式 prototype

    每次从容器中获取时,都会产生新的对象(hashcode可见)

    <bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
    

三种装配方式

  1. xml

  2. java

  3. 隐式自动装配

    <bean id="person" class="com.suren.pojo.Person">
            <property name="name" value="素人"/>
            <property name="cat" ref="cat"/>
            <property name="dog" ref="dog"/>
    </bean>
    
    //等价
    
    <bean id="person" class="com.suren.pojo.Person" autowire="byName">
            <property name="name" value="素人"/>
    </bean>
    

在这里插入图片描述
在这里插入图片描述

  1. 使用注解实现自动装配

    • 导入约束

      xmlns:context="http://www.springframework.org/schema/context"
      
    • 配置注解的支持

      <context:annotation-config>
      
    <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:annotation-config/>
    
    </beans>
    
    • @Autowired 直接在属性、方法上添加

      • 使用之后,就可以去掉set方法
      • @Nullable 等价方法 @Autowired (false)
    • 如果bean文件id和class文件不同,可以用@Qualifier(value=“想要的id”),新版本可以跑

在这里插入图片描述

5、使用注解开发

  1. 属性注入
//相当于<bean id="user" class="com.suren.pojo.User"/>
@Component
public class User {

    // 相当于<property name="name" value="素人"/>
    @Value("素人")
    public String name;

}
  1. 衍生的注解

在这里插入图片描述

功能一样,都是把类注入到容器中,组件的意思

  1. 自动装配

    - @Autowired : 自动匹配通过类型。
        如果Autowired不能唯一自动装上属性,通过@Qualifier(value="想要的id")
    - @Resource : 自动匹配通过名字。
    - @Nullable : 表示这个字段可以为空
    
  2. 作用域

  3. 小结

在这里插入图片描述

6、▶️用javaconfig实现配置

(Spring_06)

1. @Configuration

这个注解可以注册到Spring容器中(本身就是一个Component

表示这是一个配置类,等价于xml配置文件

package org.springframework.context.annotation;

@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE})
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Documented
@org.springframework.stereotype.Component
public @interface Configuration {
    @org.springframework.core.annotation.AliasFor(annotation = org.springframework.stereotype.Component.class)
    java.lang.String value() default "";

    boolean proxyBeanMethods() default true;
}
  • 配置类

    • 配置类的结合

在这里插入图片描述

在这里插入图片描述

  • 测试类

    //使用配置类,只能使用AnnotationConfig上下文获取容器,通过配置类的class对象加载
           ApplicationContext context = new AnnotationConfigApplicationContext(UserConfig.class);
            User getUser=(User)context.getBean("getUser"); //这里是方法名
            System.out.println(getUser.getName());
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值