6. 使用注解开发

空~2022年9月6日
  • Spring
大约 5 分钟

6. 使用注解开发

基于注解的 di: 通过注解完成 java 对象创建,属性赋值

  1. 加入 maven 的依赖 spring-context ,在你加入 spring-context 的同时, 间接加入 spring-aop 的依赖

    使用注解必须使用 spring-aop 依赖

    注解开发

  2. 在类中加入 spring 的注解(多个不同功能的注解)

  3. 在 spring 的配置文件中,加入一个组件扫描器的标签,说明注解在你的项目中的位置

  4. 学习的注解:

    1. @Component
    2. @Repository
    3. @Service
    4. @Controller
    5. @Value
    6. @Autowired
    7. @Resource

1. 导入 Context 约束, 增加注解支持

<?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">

  <!--声明组件扫描器(component-scan),组件就是java对象
        base-package: 指定注解在你的项目中的包名
        component-scan工作方式:  spring会扫描遍历base-package指定的包,
           把包中和子包中的所有类,找到类中的注解,按照注解的功能创建对象,或给属性赋值

       加入了component-scan标签,配置文件的变化:
        1.加入一个新的约束文件spring-context.xsd
        2.给这个新的约束文件起个命名空间的名称
    -->
  <context:component-scan base-package="pojo"/>
</beans>
  • 指定多个包的三种方式

第一种方式: 使用多次组件扫描器,指定不同的包

<context:component-scan base-package="com.bjpowernode.ba01"/>
<context:component-scan base-package="com.bjpowernode.ba02"/>

第二种方式: 使用分隔符(;或,)分隔多个包名

<context:component-scan base-package="com.bjpowernode.ba01;com.bjpowernode.ba02" />

第三种方式: 指定父包

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

2. 注解

  1. @Component

    • 创建对象的注解, 等同于<bean>的功能

    • 属性:

    • value 就是对象的名称,也就是 bean 的 id 值,value 的值是唯一的,创建的对象在整个 spring 容器中就一个

    • 省略 value@Component("user")

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

    • 位置: 在类的上面

    @Component(value = "user")
    public class User {
        // 可以在属性上
        @Value("x")
        private String name;
    }
    

    @Component(value = "user")等同于

    <bean id="user" class="com.demo.ba01.User" />
    
  2. 衍生的注解

    • @Component的衍生注解

    • dao [@Repository]

    • service[@Service]

    • controller[@Controller]

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

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

  3. @Value

    • 简单类型的属性赋值

    • 属性:

      • value 是 String 类型的,表示简单类型的属性值
    • 位置:

      • 可以在属性上, 也可以在方法上, 在属性定义的上面,无需 set 方法, 推荐使用
    @Component
    public class User {
        // 可以在属性上
        @Value("x")
        private String name;
    }
    
    @Component
    public class User {
        private String name;
        // 也可以在方法上
        @Value("x")
        public void setName(String name) {
            this.name = name;
        }
    }
    
  4. @Autowired

    • 引用类型的赋值
    • @Autowired spring 框架提供的注解,实现引用类型的赋值
    • spring 中通过注解给引用类型赋值,使用的是自动注入原理,支持 byName, byType
    • @Autowired: 默认使用的是 byType 自动注入
    • 属性: required,是一个 boolean 类型的,默认 true
      • required=true: 表示引用类型赋值失败,程序报错,并终止执行
      • required=false: 引用类型如果赋值失败, 程序正常执行,引用类型是 null
    • 位置:
      • 可以在属性上, 也可以在方法上, 在属性定义的上面,无需 set 方法, 推荐使用
    public class Student {
        @Autowired
        private School school;
    }
    
    • 如果要使用 byName 方式,需要做的是:

    • 在属性上面加入@Autowired

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

    public class Student {
        @Autowired(required = false)
        @Qualifier("school")
        private School school;
    }
    
  5. @Resource

    • 引用类型
    • 来自 jdk 中的注解,spring 框架提供了对这个注解的功能支持,可以使用它给引用类型赋值, 使用的也是自动注入原理,支持 byName, byType ,默认是 byName
    • 位置:
      • 可以在属性上, 也可以在方法上, 在属性定义的上面,无需 set 方法, 推荐使用
    • 默认是 byName: 先使用 byName 自动注入,如果 byName 赋值失败,再使用 byType
    • @Resource 只使用 byName 方式,需要增加一个属性 name
    • name 的值是 bean 的 id(名称)
    public class Student {
        @Resource
        private School school;
        @Resource(name = "school")
        private School school2;
    }
    
  6. @Scope("xxx")

    修改作用域

    • singleton 单例模式 -- 全局有且仅有一个实例

    • prototype 原型模式 -- 每次获取 Bean 的时候会有一个新的实例

    • request -- request 表示该针对每一次 HTTP 请求都会产生一个新的 bean,同时该 bean 仅在当前 HTTP request 内有效

    • session -- session 作用域表示该针对每一次 HTTP 请求都会产生一个新的 bean,同时该 bean 仅在当前 HTTP session 内有效

    • globalsession -- global session 作用域类似于标准的 HTTP Session 作用域,不过它仅仅在基于 portlet 的 web 应用中才有意义

    @Component
    @Scope("prototype")
    public class User {
        private String name;
        @Value("x")
        public void setName(String name) {
            this.name = name;
        }
    }
    
  7. 小结

    • xml: 万能, 适用性任何场景, 维护简单方便

    • 注解: 不是自己的类使用不了, 维护复杂

    • xml 与注解的最佳实践

      1. xml 管理 bean
      2. 注解完成属性的注入