Spring——IoC中基于注解的DI

简介: Spring——IoC中基于注解的DI

文章目录:


1.基于注解的DI概述

1.1 使用多个 context:component-scan 指定不同的包路径

1.2 指定 base-package 的值使用分隔符

1.3 base-package 指定到父包名

2.注解的使用

2.1 @Component@Value(存在于Spring中,用于给简单类型的属性赋值)

2.2 @Autowired(存在于Spring中,用于给引用类型的属性赋值,byType

2.3 @Autowired@Qualifier(存在于Spring中,用于给引用类型的属性赋值,byName

2.4 @Resource(存在于jdk中,用于给引用类型的属性赋值)

3.对比——基于XMLDI和基于注解的DI

3.1 XML方式的优缺点 

3.2 注解方式的优缺点 

3.3 总体来说,DI还是以注解为主,XML为辅 

4.Spring IoC总结 


1.基于注解的DI概述


在这里我们主要介绍以下几种注解:👇👇👇

1.    创建对象的注解:@Component@Repository@Service@Controller。(来自Spring框架)

2.    简单类型的对象属性赋值:@Value。(来自Spring框架)

3.    引用类型的对象属性赋值:@Autowired@Qualifier。(来自Spring框架)

4.    引用类型的对象属性赋值:@Resource。(来自JDK

对于 DI 使用注解,将不再需要在 Spring 配置文件中声明 bean 实例。Spring 中使用注解,需要在原有 Spring 运行环境基础上再做一些改变。需要在 Spring 配置文件中配置组件扫描器,用于在指定的基本包中扫描注解。 

在基于注解的DI中,我们的Spring配置文件中将不再需要<bean>标签,而是在其中添加

<context:component-scan base-package="XXX" /> 这句代码。

在指定的包中扫描注解一共有以下三种方式:👇👇👇


1.1 使用多个context:component-scan 指定不同的包路径

<!--
    声明组件扫描器:使用注解必须加上这个语句
    component-scan: 组件扫描器,组件是Java对象
    属性base-package: 表示项目中的包名
    框架会扫描这个包和子包中的所有类,找到类中的所有注解,
    遇到注解后,按照注解表示的功能,去创建对象、给属性赋值
-->
<context:component-scan base-package="com.bjpowernode.ba01" />
<context:component-scan base-package="com.bjpowernode.ba02" />

1.2 指定 base-package 的值使用分隔符

<!-- 可以使用分隔符(;或者,)指定多个包 -->
<context:component-scan base-package="com.bjpowernode.ba01;com.bjpowernode.ba02" />
<context:component-scan base-package="com.bjpowernode.ba01,com.bjpowernode.ba02" />

1.3 base-package 指定到父包名

base-package的值表是基本包,容器启动会扫描包及其子包中的注解,当然也会扫描到子包下级的子包。所以 base-package 可以指定一个父包就可以。 但不建议使用顶级的父包,扫描的路径比较多,导致容器启动时间变慢。

<!-- 也可以指定父包 -->
<context:component-scan base-package="com.bjpowernode" />

2.注解的使用


2.1 @Component@Value(存在于Spring中,用于给简单类型的属性赋值)

@Component: 表示创建对象,对象放到容器中,作用是 <bean>
         
属性: value,表示对象名称,也就是 <bean> 标签中的 id 属性值
         
位置: 在类的上面,表示创建此类的对象

@Component功能相同的创建对象的注解:

1.    @Repository : 放在dao接口的实现类上面,表示创建dao对象,能访问数据库

2.    @Service : 放在业务层接口的实现类上面,表示创建业务层对象,具有事务的功能

3.    @Controller : 放在控制器类的上面,表示创建控制器对象,能够接收请求,把请求的处理结果显示给用户

@Repository@Service@Controller 是对@Component注解的细化,标注不同层的对象。

简单类型的属性赋值:@Value
     
属性: value,表示属性值,可以省略
     
位置:1) 在属性定义的上面,无需set方法,推荐使用
                 2)
set方法上面

<?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
       https://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.bjpowernode.ba01" />
</beans>
package com.bjpowernode.ba01;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
 *  @Component: 表示创建对象,对象放到容器中,作用是 <bean>
 *         属性: value,表示对象名称,也就是 <bean> 标签中的 id 属性值
 *         位置: 在类的上面,表示创建此类的对象
 *
 *  @Component(value = "myStudent") 等同于
 *  @Component("myStudent") 等同于
 *  <bean id="myStudent" class="com.bjpowernode.ba01.Student" />
 *
 *  如果写成 @Component,则会使用框架的默认对象名称(类名首字母小写student)
 */
@Component("myStudent")
public class Student {
    /**
     *  简单类型的属性赋值:@Value
     *  属性: value,表示属性值,可以省略
     *  位置:1)在属性定义的上面,无需set方法,推荐使用
     *       2)在set方法上面
     */
    @Value("张三")
    private String name;
    @Value("20")
    private int age;
    public Student() {
        System.out.println("Student类的无参构造方法被执行了");
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package com.bjpowernode;
import com.bjpowernode.ba01.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 *
 */
public class MyTest {
    @Test
    public void test01() {
        String config="applicationContext.xml";
        ApplicationContext ctx=new ClassPathXmlApplicationContext(config);
        Student student= (Student) ctx.getBean("myStudent");
        System.out.println("student === " + student);
    }
}

2.2 @Autowired(存在于Spring中,用于给引用类型的属性赋值,byType

引用类型:@Autowired

spring框架提供的,给引用类型赋值的,使用自动注入原理。支持byNamebyType,默认是byType

属性:requiredboolean类型的属性,默认为true
           true
spring在创建容器对象时,会检查引用类型是否赋值成功,如果赋值失败,终止程序运行并报错。
           false
:如果引用类型赋值失败,程序正常执行不会报错,此时引用类型的值为null

位置:1)在属性定义的上面,无需set方法,推荐使用
          2)
set方法上面

byType自动注入:👇👇👇

<?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
       https://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.bjpowernode.ba02"/>
</beans>
package com.bjpowernode.ba02;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
 *
 */
@Component("mySchool")
public class School {
    @Value("北京大学")
    private String name;
    @Value("北京海淀区")
    private String address;
    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
package com.bjpowernode.ba02;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("myStudent")
public class Student {
    @Value("张三")
    private String name;
    @Value("20")
    private int age;
    /**
     *  引用类型:@Autowired
     *  spring框架提供的,给引用类型赋值的,使用自动注入原理
     *  支持byName、byType,默认是byType
     *  属性:required:boolean类型的属性,默认为true
     *       true:spring在创建容器对象时,会检查引用类型是否赋值成功,如果赋值失败,终止程序运行并报错。
     *       false:如果引用类型赋值失败,程序正常执行不会报错,此时引用类型的值为null。
     *  位置:1)在属性定义的上面,无需set方法,推荐使用
     *       2)在set方法上面
     *  byType自动注入
     */
    @Autowired(required = true)
    private School school;
    public Student() {
        System.out.println("Student类的无参构造方法被执行了");
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}
package com.bjpowernode;
import com.bjpowernode.ba02.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 *
 */
public class MyTest02 {
    @Test
    public void test01() {
        String config="applicationContext02.xml";
        ApplicationContext ctx=new ClassPathXmlApplicationContext(config);
        Student student= (Student) ctx.getBean("myStudent");
        System.out.println("student === " + student);
    }
}

2.3 @Autowired@Qualifier(存在于Spring中,用于给引用类型的属性赋值,byName

引用类型:@Autowired

spring框架提供的,给引用类型赋值的,使用自动注入原理。支持byNamebyType,默认是byType

属性:requiredboolean类型的属性,默认为true
           true
spring在创建容器对象时,会检查引用类型是否赋值成功,如果赋值失败,终止程序运行并报错。
           false
:如果引用类型赋值失败,程序正常执行不会报错,此时引用类型的值为null

位置:1) 在属性定义的上面,无需set方法,推荐使用
         2)
set方法上面

byName自动注入:
      1) @Autowired
:给引用类型赋值
      2) @Qualifier(value="bean
id"):从容器中找到指定名称的对象,把这个对象赋值给引用类型 

<?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
       https://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.bjpowernode.ba03"/>
</beans>
package com.bjpowernode.ba03;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
 *
 */
@Component("mySchool")
public class School {
    @Value("清华大学")
    private String name;
    @Value("北京海淀区")
    private String address;
    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
package com.bjpowernode.ba03;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("myStudent")
public class Student {
    @Value("李四")
    private String name;
    @Value("25")
    private int age;
    /**
     *  引用类型:@Autowired
     *  spring框架提供的,给引用类型赋值的,使用自动注入原理
     *  支持byName、byType,默认是byType
     *  属性:required:boolean类型的属性,默认为true
     *       true:spring在创建容器对象时,会检查引用类型是否赋值成功,如果赋值失败,终止程序运行并报错。
     *       false:如果引用类型赋值失败,程序正常执行不会报错,此时引用类型的值为null。
     *  位置:1)在属性定义的上面,无需set方法,推荐使用
     *       2)在set方法上面
     *  byName自动注入:
     *  1)@Autowired:给引用类型赋值
     *  2)@Qualifier(value="bean的id"):从容器中找到指定名称的对象,把这个对象赋值给引用类型
     */
    @Autowired(required = true)
    @Qualifier(value = "mySchool")
    private School school;
    public Student() {
        System.out.println("Student类的无参构造方法被执行了");
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}
package com.bjpowernode;
import com.bjpowernode.ba03.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 *
 */
public class MyTest03 {
    @Test
    public void test01() {
        String config="applicationContext03.xml";
        ApplicationContext ctx=new ClassPathXmlApplicationContext(config);
        Student student= (Student) ctx.getBean("myStudent");
        System.out.println("student === " + student);
    }
}

2.4 @Resource(存在于jdk中,用于给引用类型的属性赋值)

引用类型:@Resource,来自jdk中,给引用类型赋值,支持byNamebyType,默认是byNameSpring框架支持这个注解。

位置:1) 在属性定义的上面,无需set方法,推荐使用
         2)
set方法上面

@Resource:先使用byName赋值,如果赋值失败,再使用byType
@Resource(name="mySchool")
:表示只使用byName

如果使用jdk1.8,则带有@Resource注解;如果高于jdk1.8,则没有这个注解。如需使用,需要在pom.xml文件中加入依赖:👇👇👇

<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>
<?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
       https://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.bjpowernode.ba04"/>
</beans>
package com.bjpowernode.ba04;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
 *
 */
@Component("mySchool")
public class School {
    @Value("北京大学")
    private String name;
    @Value("北京海淀区")
    private String address;
    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
package com.bjpowernode.ba04;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component("myStudent")
public class Student {
    @Value("张起灵")
    private String name;
    @Value("18")
    private int age;
    /**
     *  引用类型:@Resource,来自jdk中,给引用类型赋值,支持byName、byType,默认是byName
     *  位置:1)在属性定义的上面,无需set方法,推荐使用
     *       2)在set方法上面
     *  @Resource:先使用byName赋值,如果赋值失败,再使用byType
     *  @Resource(name="mySchool"):表示只使用byName
     *  如果使用jdk1.8,则带有@Resource注解;
     *  如果高于jdk1.8,则没有这个注解。如需使用,需要在pom.xml文件中加入依赖
     */
    @Resource
    private School school;
    public Student() {
        System.out.println("Student类的无参构造方法被执行了");
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}
package com.bjpowernode;
import com.bjpowernode.ba04.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 *
 */
public class MyTest04 {
    @Test
    public void test01() {
        String config="applicationContext04.xml";
        ApplicationContext ctx=new ClassPathXmlApplicationContext(config);
        Student student= (Student) ctx.getBean("myStudent");
        System.out.println("student === " + student);
    }
}


3.对比——基于XML的DI和基于注解的DI


3.1 XML方式的优缺点 

优点:配置和代码是相分离的。

           xml中做修改,无需编译代码,只需重启服务器即可将新的配置加载。

缺点:编写麻烦,效率低,如果面对大型项目就显得过于复杂。


3.2 注解方式的优缺点 

优点:方便、直观、高效(代码少,没有配置文件的书写那么复杂) 

缺点:以硬编码的方式写入到 Java 代码中,修改是需要重新编译代码的。


3.3 总体来说,DI还是以注解为主,XML为辅 

4.Spring IoC总结


IoC用来管理对象,把对象放在容器中,进而创建对象、给对象属性赋值、管理对象之间的依赖关系。

IoC通过管理对象实现解耦合。往往解决的是业务逻辑对象之间的耦合关系,也就是servicedao之间的解耦合。

适合交给Spring容器的对象:service对象、dao对象、工具类对象。

不适合交给Spring容器的对象:实体类,servletlistenerfilterweb中的对象(它们是由tomcat创建和管理的)。

目录
打赏
0
0
0
0
85
分享
相关文章
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
203 26
SpringBoot缓存注解使用
Spring Boot 提供了一套方便的缓存注解,用于简化缓存管理。通过 `@Cacheable`、`@CachePut`、`@CacheEvict` 和 `@Caching` 等注解,开发者可以轻松地实现方法级别的缓存操作,从而提升应用的性能和响应速度。合理使用这些注解可以大大减少数据库的访问频率,优化系统性能。
223 89
Spring MVC常用的注解
@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中 的所有响应请求的方法都是以该地址作为父路径。 @RequestBody:注解实现接收http请求的json数据,将json转换为java对象。 @ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户。 @Controller:控制器的注解,表示是表现层,不能用用别的注解代替 @RestController : 组合注解 @Conntroller + @ResponseBody @GetMapping , @PostMapping , @Put
Spring Boot的核心注解是哪个?他由哪几个注解组成的?
Spring Boot的核心注解是@SpringBootApplication , 他由几个注解组成 : ● @SpringBootConfiguration: 组合了- @Configuration注解,实现配置文件的功能; ● @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项 ● @ComponentScan:Spring组件扫描
什么是Spring IOC 和DI ?
IOC : 控制翻转 , 它把传统上由程序代码直接操控的对象的调用权交给容 器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转 移,从程序代码本身转移到了外部容器。 DI : 依赖注入,在我们创建对象的过程中,把对象依赖的属性注入到我们的类中。
SpringBoot+@Async注解一起用,速度提升
本文介绍了异步调用在高并发Web应用性能优化中的重要性,对比了同步与异步调用的区别。同步调用按顺序执行,每一步需等待上一步完成;而异步调用无需等待,可提升效率。通过Spring Boot示例,使用@Async注解实现异步任务,并借助Future对象处理异步回调,有效减少程序运行时间。
保姆级Spring AI 注解式开发教程,你肯定想不到还能这么玩!
这是一份详尽的 Spring AI 注解式开发教程,涵盖从环境配置到高级功能的全流程。Spring AI 是 Spring 框架中的一个模块,支持 NLP、CV 等 AI 任务。通过注解(如自定义 `@AiPrompt`)与 AOP 切面技术,简化了 AI 服务集成,实现业务逻辑与 AI 基础设施解耦。教程包含创建项目、配置文件、流式响应处理、缓存优化及多任务并行执行等内容,助你快速构建高效、可维护的 AI 应用。
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于注解的整合
本文介绍了Spring Boot集成MyBatis的两种方式:基于XML和注解的形式。重点讲解了注解方式,包括@Select、@Insert、@Update、@Delete等常用注解的使用方法,以及多参数时@Param注解的应用。同时,针对字段映射不一致的问题,提供了@Results和@ResultMap的解决方案。文章还提到实际项目中常结合XML与注解的优点,灵活使用两者以提高开发效率,并附带课程源码供下载学习。
34 0
|
2月前
|
SpringBoot:SpringBoot通过注解监测Controller接口
本文详细介绍了如何通过Spring Boot注解监测Controller接口,包括自定义注解、AOP切面的创建和使用以及具体的示例代码。通过这种方式,可以方便地在Controller方法执行前后添加日志记录、性能监控和异常处理逻辑,而无需修改方法本身的代码。这种方法不仅提高了代码的可维护性,还增强了系统的监控能力。希望本文能帮助您更好地理解和应用Spring Boot中的注解监测技术。
82 16
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等