6. 使用注解开发
6. 使用注解开发
基于注解的 di: 通过注解完成 java 对象创建,属性赋值
加入 maven 的依赖 spring-context ,在你加入 spring-context 的同时, 间接加入 spring-aop 的依赖
使用注解必须使用 spring-aop 依赖
在类中加入 spring 的注解(多个不同功能的注解)
在 spring 的配置文件中,加入一个组件扫描器的标签,说明注解在你的项目中的位置
学习的注解:
@Component
@Repository
@Service
@Controller
@Value
@Autowired
@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. 注解
@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" />
衍生的注解
@Component
的衍生注解dao [
@Repository
]service[
@Service
]controller[
@Controller
]
以上三个注解的使用语法和
@Component
一样的 都能创建对象,但是这三个注解还有额外的功能@Repository
,@Service
,@Controller
是给项目的对象分层的@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; } }
@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; }
@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; }
@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; } }
小结
xml: 万能, 适用性任何场景, 维护简单方便
注解: 不是自己的类使用不了, 维护复杂
xml 与注解的最佳实践
- xml 管理 bean
- 注解完成属性的注入