• Java--Spring之IoC控制反转;基于注解的DI


    基于XML配置文件的DI请参考上文

    https://blog.csdn.net/MinggeQingchun/article/details/122880488

    二、基于注解的DI

    DI 使用注解,将不再需要在 Spring 配置文件中声明 bean 实例

    Spring 中使用注解,需要在 Spring 配置文件中配置组件扫描器,用于在指定的基本包中扫描注解

    1、声明组件扫描器(component-scan),组件就是Java对象

    base-package:指定注解在项目中的包名

    2、component-scan工作原理:

    spring会扫描遍历base-package指定的包, 扫描包和子包中的所有类,找到类中的注解,按照注解创建Java对象,或者给属性赋值

    3、加入标签,配置文件发生变化

    (1)加入了新的约束文件:spring-context.xsd

    (2)给这个新的约束文件起个命名空间的名称

    xmlns:context="http://www.springframework.org/schema/context" http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.x

     4、指定多个包的3种方式

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

    1. <context:component-scan base-package="com.mycompany.package1" />
    2. <context:component-scan base-package="com.mycompany.package2" />

    (2)指定 base-package 的值使用分隔符

    分隔符可以使用逗号(,)分号(;)还可以使用空格,不建议使用空格

    <context:component-scan base-package="com.mycompany.package1;com.mycompany.package2" />

    (3)base-package 是指定到父包名

    但不建议直接使用com,这样会扫描磁盘中所有文件夹,导致效率降低

    <context:component-scan base-package="com.mycompany" />

    spring配置文件 applicationContext.xml 

    1. <beans xmlns="http://www.springframework.org/schema/beans"
    2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xmlns:context="http://www.springframework.org/schema/context"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans
    5. http://www.springframework.org/schema/beans/spring-beans.xsd
    6. http://www.springframework.org/schema/context
    7. https://www.springframework.org/schema/context/spring-context.xsd">
    8. <context:component-scan base-package="com.mycompany.p2valuenormal" />
    9. <context:property-placeholder location="classpath:objectvalue.properties" />
    10. beans>

    (一)@Component@Repository@Service@Controller注解

    1、@Component :创建对象,等同 标签功能

    (1)属性:value 对象的名称,就是 的 id 值 value值唯一,创建对象在整个spring容器中就仅有一个

    (2)位置:类上面

    (3)语法:

    1. @Component(value = "myUser")
    2. 等同
    3. "myUser" class="com.xx.User" />

    spring中和@Component功能一致,创建对象的注解还有:

    1、@Repository(持久层类的上面):放在dao的实现类上面, 表示创建dao对象,dao对象是能访问数据库的

    2、@Service (业务层类的上面):放在service的实现类上面, 创建service对象,service对象是做业务处理,可以有事务等功能的

    3、@Controller (控制器的上面):放在控制器(处理器)类的上面,创建控制器对象的, 控制器对象,能够接受用户提交的参数,显示请求的处理结果

    以上三个注解的使用语法和@Component一样的,都能创建对象,但是这三个注解还有额外的功能

    @Repository ,@Service,@Controller是给项目的对象分层的

    @Component有3中用法

    (1)使用value属性,指定对象名称 @Component(value = "myUser")

    (2)省略value关键字 @Component("myUser")

    (3)不指定对象名称,由spring提供默认名称: 类名的首字母小写 @Component

    1. /*
    2. 1、使用value属性,指定对象名称
    3. @Component(value = "myUser")
    4. 2、省略value关键字
    5. @Component("myUser")
    6. 3、不指定对象名称,由spring提供默认名称: 类名的首字母小写
    7. @Component
    8. */
    9. //使用value属性,指定对象名称
    10. @Component(value = "myUser")
    11. public class User {
    12. }

    测试代码

    1. @Test
    2. public void testComponent(){
    3. String config = "applicationContext.xml";
    4. ApplicationContext ac = new ClassPathXmlApplicationContext(config);
    5. User user = (User) ac.getBean("myUser");
    6. //不指定对象名称,由spring提供默认名称: 类名的首字母小写 @Component
    7. // User user = (User) ac.getBean("user");
    8. System.out.println(user);
    9. }

    (二)@Value简单类型赋值

    @Value : 简单类型属性赋值

    (1)属性: value   

    【1】String类型,表示简单类型属性值

    【2】也可使用属性配置文件加载,@Value("${属性的key}")

    在 applicationContext.xml 文件中加载属性配置文件

    1. <context:property-placeholder location="classpath:objectvalue.properties" />

     objectvalue.properties属性配置文件

    1. myName=admin
    2. myAge=18

    使用

    1. @Value("${myName}")//使用属性配置文件中的数据
    2. private String userName;
    3. // @Value("18")
    4. @Value("${myAge}")//使用属性配置文件中的数据
    5. private int age;

    (2)位置: 1、在属性定义上面,无需set方法(建议使用);2、在set方法上面

    1. //使用value属性,指定对象名称
    2. @Component(value = "myUser")
    3. public class User {
    4. /**
    5. * @Value : 简单类型属性赋值
    6. * 属性: value String类型,表示简单类型属性值
    7. * 也可使用属性配置文件加载,@Value("${属性的key}")
    8. * 位置: 1、在属性定义上面,无需set方法(建议使用)
    9. * 2、在set方法上面
    10. */
    11. // @Value("admin")
    12. @Value("${myName}")//使用属性配置文件中的数据
    13. private String userName;
    14. // @Value("18")
    15. @Value("${myAge}")//使用属性配置文件中的数据
    16. private int age;
    17. public User() {
    18. System.out.println("spring会调用User类的无参构造方法创建对象");
    19. }
    20. // @Value("admin")
    21. public void setUserName(String userName) {
    22. this.userName = userName;
    23. }
    24. // @Value("18")
    25. public void setAge(int age) {
    26. this.age = age;
    27. }
    28. }

    (三)@Autowired

    1、byType

    @Autowired 默认使用的是 byType自动注入

    位置: 1、在属性定义的上面,无需set方法(建议使用) 2、在set方法的上面

    1. //使用value属性,指定对象名称
    2. @Component(value = "myUser")
    3. public class User {
    4. /**
    5. * 引用类型 @Autowired(byType)
    6. * @Autowired :spring框架提供的注解,实现引用类型赋值
    7. * spring通过注解给引用类型赋值,使用的是自动注入原理,支持 byName,byType
    8. * @Autowired 默认使用的是 byType自动注入
    9. *
    10. * 位置:
    11. * 1、在属性定义的上面,无需set方法(建议使用)
    12. * 2、在set方法的上面
    13. */
    14. @Autowired
    15. private Address address;
    16. }
    17. @Component(value = "myAddress")
    18. public class Address {
    19. }

    2、byName和@Qualifier

    @Autowired使用byName方式

    在属性上加入 @Autowired;在属性上还要加上@Qualifier(value = "bean的id"):表示使用指定名称的bean完成赋值

    注:@Autowired 和 @Qualifier 注解没有先后顺序之分,一般先声明功能,将@Autowired写在上面

    1. //使用value属性,指定对象名称
    2. @Component(value = "myUser")
    3. public class User {
    4. @Value("admin")
    5. // @Value("${myName}")//使用属性配置文件中的数据
    6. private String userName;
    7. @Value("18")
    8. // @Value("${myAge}")//使用属性配置文件中的数据
    9. private int age;
    10. /**
    11. * 引用类型 @Autowired(byType)
    12. * @Autowired :spring框架提供的注解,实现引用类型赋值
    13. * spring通过注解给引用类型赋值,使用的是自动注入原理,支持 byName,byType
    14. * 1、@Autowired 默认使用的是 byType自动注入
    15. * 位置:
    16. * (1)在属性定义的上面,无需set方法(建议使用)
    17. * (2)在set方法的上面
    18. *
    19. * 2、@Autowired使用byName方式
    20. * 在属性上加入 @Autowired
    21. * 在属性上还要加上@Qualifier(value = "bean的id"):表示使用指定名称的bean完成赋值
    22. * 注:
    23. * @Autowired@Qualifier 注解没有先后顺序之分,一般先声明功能,将@Autowired写在上面
    24. */
    25. @Autowired
    26. @Qualifier("myAddress")
    27. private Address address;
    28. }
    29. @Component(value = "myAddress")
    30. public class Address {
    31. }

    3、required属性

    required 属性,是一个Boolean类型,默认 true

    required = true :表示引用类型赋值失败,程序报错,并终止执行

    required = false :表示引用类型赋值失败,程序正常执行,引用类型为 null

    一般无特殊请款,建议使用required = true,将问题尽早暴露,防止后续出现空指针异常

    1. required = true :如果spring找不到引用对象bean的id,程序报错如下
    2. NoSuchBeanDefinitionException: No qualifying bean of type 'com.mycompany.p5referenceautowiredrequired.Address' available:
    3. expected at least 1 bean which qualifies as autowire candidate. Dependency annotations:
    4. {@org.springframework.beans.factory.annotation.Autowired(required=true),
    5. @org.springframework.beans.factory.annotation.Qualifier(value=myAddress-1)}
    1. //使用value属性,指定对象名称
    2. @Component(value = "myUser")
    3. public class User {
    4. /**
    5. * 引用类型 @Autowired(byType)
    6. * required 属性,是一个Boolean类型,默认 true
    7. * required = true :表示引用类型赋值失败,程序报错,并终止执行
    8. * required = false :表示引用类型赋值失败,程序正常执行,引用类型为 null
    9. * 一般无特殊请款,建议使用required = true,将问题尽早暴露,防止后续出现空指针异常
    10. *
    11. * required = true :如果spring找不到引用对象bean的id,程序报错如下
    12. NoSuchBeanDefinitionException: No qualifying bean of type 'com.mycompany.p5referenceautowiredrequired.Address' available:
    13. expected at least 1 bean which qualifies as autowire candidate. Dependency annotations:
    14. {@org.springframework.beans.factory.annotation.Autowired(required=true),
    15. @org.springframework.beans.factory.annotation.Qualifier(value=myAddress-1)}
    16. *
    17. */
    18. @Autowired(required = false)
    19. @Qualifier("myAddress-1")
    20. private Address address;
    21. }
    22. @Component(value = "myAddress")
    23. public class Address {
    24. }

    (四)@Resource

    @Resource :来自JDK中的注解(包名:javax.annotation.Resource),spring框架提供了对该注解的功能支持,可以使用它给引用类型赋值

    @Resource 工作原理:使用自动注入,支持byName, byType

    @Resource 注解若不带任何参数,默认是 按名称的方式注入 byName(先使用byName自动注入,如果byName赋值失败,再使用byType)

    位置:1、在属性定义的上面,无需set方法(建议使用);2、在set方法上面

    1、默认byName,失败则使用byType

    1. //使用value属性,指定对象名称
    2. @Component(value = "myUser")
    3. public class User {
    4. /**
    5. * 引用类型 @Resource
    6. * @Resource :来自JDK中的注解(包名:javax.annotation.Resource),spring框架提供了对该注解的功能支持,可以使用它给引用类型赋值
    7. * @Resource 工作原理:使用自动注入,支持byName, byType
    8. * @Resource 注解若不带任何参数,默认是 按名称的方式注入 byName(先使用byName自动注入,如果byName赋值失败,再使用byType)
    9. * 位置:
    10. * 1、在属性定义的上面,无需set方法(建议使用)
    11. * 2、在set方法上面
    12. */
    13. //默认是byName: 先使用byName自动注入,如果byName赋值失败,再使用byType
    14. @Resource
    15. private Address address;
    16. }

    2、使用byName

    @Resource 只使用byName方式,需要增加一个属性 name;name的值为 bean 的 id名称

    1. //使用value属性,指定对象名称
    2. @Component(value = "myUser")
    3. public class User {
    4. /**
    5. * 引用类型 @Resource
    6. * @Resource 只使用byName方式,需要增加一个属性 name
    7. * name的值为 bean 的 id名称
    8. */
    9. //只使用byName
    10. @Resource(name = "myAddress")
    11. private Address address;
    12. }
    13. @Component(value = "myAddress")
    14. public class Address {
    15. }

  • 相关阅读:
    DGS之文件上传
    mysql有关查询的操作
    CornerNet-Lite训练自己的数据集
    What is an HTTP Flood DDoS attack?
    英语翻译器-免费英语自动批量翻译器
    安卓gradle使用
    node.js 简介 以及 模块化 的介绍
    WebServer——二:线程池
    Postman全局配置变量token
    Linux 的 grep
  • 原文地址:https://blog.csdn.net/MinggeQingchun/article/details/122882311