持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情
写在前面😘
大一电子信息工程新生,请多多关照,希望能在掘金记录自己的学习历程!
【Spring 学习笔记】 系列教程基于Spring 5.2.10.RELEASE讲解 。
一、注解开发简介
有关Spring IoC的xml文件配置开发终于介绍了,但是感觉写配置文件好麻烦,没体验到Spring简化开发的过程啊。
其实,要想真正简化开发,害得用到Spring的注解开发。
接下来,就让大牛角来讲解Spring 注解开发吧!
1️⃣什么是注解开发
指的是在类或者方法上加入特定的注解(@XXX),完成特定功能的开发。
@Component
public class XXX{}
2️⃣spring注解开发历程
- Spirng2.x开始支持注解开发
@Component等 目的:起初,只是为了简化XML的配置,作为XML的有益补充 - Spring3.x 纯注解开发
@Configuration等 目的:彻底替换XML,基于纯注解开发 - Spirng4.x SpringBoot 提倡使用注解进行常见开发
3️⃣注解开发优点
使用注解的形式替代 xml 配置,将繁杂的 Spring 配置文件从工程中消除掉,简化开发。
二、原始注解开发(Spring 2.x)
Spring 原始注解:主要是替代
<Bean>的配置。原始注解(也称基础注解),仅仅是简化XML的配置,并不能完全替代XML(如还是需要用到XML的包扫描)。
1️⃣开启注解功能
- 开启注解功能,需要在 Spring 的配置文件中配置注解扫描
<!--base-package: 添加注解的类所在的包位置-->
<context:component-scan base-package="com.bighorn"/>
注意点:记得在<beans>标签里打开context命名空间
- 说明:
- 在进行包所扫描时,会对配置的包及其子包中所有文件进行扫描。
- 扫描时仅读取 spring 可识别的注解。
- 扫描结束后会将有效注解转化为 spring 对应的资源加入 IoC 容器。
- 注意:
- 记得在
<beans>标签里打开context命名空间 - 无论是注解开发还是 XML 开发,最终都是将资源加载到 IoC 容器中,差别就是数据读取方式不同。
- 注解的
加载效率优于 XML 配置文件。
- 记得在
2️⃣Bean定义注解
2.1@Component
- 类型:类注解
- 位置:类定义上方。
- 作用:设置该类为 spring 管理的 bean ,替换Spring配置文件中的
<bean>标签。 - 注意点:id可以不写,默认id是首字母小写的类名
示例👇
@Component("user")
public class User{
...
}
这相当于这样xml配置中定义bean
<bean id="user" class="com.bighorn.pojo.User"/>
2.2@Component衍生注解
项目开发时一般会将程序分层:控制层(controller/web),业务层(service),持久层(dao)。
为了更好区分每一层的作用,spring衍生了@Component注解:@Controller、@Service、@Repository
| 注解 | 说明 |
|---|---|
@Component | 使用在类上用于实例化 Bean |
@Controller | 使用在 web 层类上用于实例化 Bean |
@Service | 使用在 service 层类上用于实例化 Bean |
@Repository | 使用在 dao 层类上用于实例化 Bean |
注意:本质上这些衍生注解就是@Component 作用,细节以及用法完全一致
目的:更加准确的表达一个类型的作用。
示例👇
/*创建web层对象**/
@Controller
public class UserController {
...
}
/*创建service层对象**/
@Service
public class UserServiceImpl implements UserService {
...
}
/*创建dao层对象**/
@Repository
public class UserDaoImpl implements UserDao {
...
}
3️⃣Bean作用域注解
@Scope
- 类型:类注解
- 位置:类定义上方。
- 作用:设置该类作为 bean 对应的 scope 属性。
- 注意:不加**@Scope**,默认是singleton单例模式
示例👇
@Component //默认id:user
@Scope("prototype")//非单例模式
public class User {
}
4️⃣Bean生命周期注解
4.1@PostConstruct
- 类型:方法注解
- 位置:方法定义上方。
- 作用:设置该类作为 bean 对应的初始化方法。
4.2@PreDestory
- 类型:方法注解
- 位置:方法定义上方。
- 作用:设置该类作为 bean 对应的销毁方法。
4.3示例👇
- 如果你使用的JDK是9以后的,你可能需要先导入
javax.annotation包,才能使用生命周期相关注解。
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
- 定义初始化方法和销毁方法,并在方法上方添加相关注解。
@Component
public class User {
// 初始化方法
@PostConstruct
public void init(){
System.out.println("这是初始化回调方法");
}
//销毁回调方法
@PreDestory
public void destroy(){
System.out.println("这是销毁回调方法");
}
}
这相当于这样配置xml
<!--通过XML配置指定回调方法-->
<bean id="user" class="com.bighorn.pojo.User" init-method="init" destroy-method="destroy">
</bean>
- 编写运行程序
public static void main(String[] args) {
//获取IoC容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//从容器中获取对象
User user = context.getBean(User.class);
System.out.println(user);
//手动关闭容器
context.close();
}
- 运行结果如下
5️⃣Bean属性注入注解
5.1@Autowired、@Qualifier
- 类型:属性注解、方法注解
- 位置:属性定义上方,也可以是方法定义上方。
- 作用:
引用类型注入 - 说明:@Autowired 默认按类型装配,指定 @Qualifier 后则可以指定装配的 bean 的 id 。
- 相关属性:
- required:定义该属性是否允许为 null 。
- 注意:@Qualifier不能独立使用,必须和@Autowired一起使用
案例1:按照Bean类型注入
- 编写dao层实现类
@Repository
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("这是UserDaoImpl的save方法");
}
}
- 编写service层实现类,在成员属性userDao上面添加
@Autowired注解,spring就会自动根据UserDao这个类型去找相应的bean注入。
- 注意:@Autowired可以写在属性上,也可也写在setter方法上,最简单的处理方式是
写在属性上并将setter方法删除掉
@Service
public class UserServiceImpl implements UserService {
//@Autowired 默认按类型装配
@Autowired
private UserDao userDao;
@Override
public void save() {
userDao.save();
System.out.println("这是UserServiceImpl的save方法");
}
}
- 编写运行程序
public static void main(String[] args) {
//获取IoC容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//从容器中获取对象
UserServiceImpl userService = context.getBean(UserServiceImpl.class);
//调用save方法
userService.save();
}
- 运行结果如下👇
案例2:按照Bean名称注入
在案例1已经验证了@Autowired是按照类型注入,但如果UserDao接口有多个实现类:UserDaoImpl2、UserDaoImpl3、UserDaoImpl4。。。
此时,按照类型注入就无法区分到底注入哪个对象,解决方案:按照名称注入,指定 @Qualifier 后则可以指定装配的 bean 的 id。
- 编写多个dao层的实现类,并分别为它们设置bean的id(关键)
//第一个实现类
@Repository("UserDao1")
public class UserDaoImpl1 implements UserDao {
@Override
public void save() {
System.out.println("这是第一个实现类的save方法");
}
}
//第二个实现类
@Repository("UserDao2")
public class UserDaoImpl2 implements UserDao {
@Override
public void save() {
System.out.println("这是第二个实现类的save方法");
}
}
//第三个实现类
@Repository("UserDao3")
public class UserDaoImpl3 implements UserDao {
@Override
public void save() {
System.out.println("这是第三个实现类的save方法");
}
}
- 编写service层实现类,在成员属性userDao上面添加
@Autowired注解,并使用@Qualifier(" ")指定要注入的bean。
注意点
- AutoWired注解基于类型进行注入注入对象的类型,必须与目标成员变量类型相同或者是其子类(实现类)
- AutoWired 配合Qualifier注解基于名称进行注入,注入对象的id值必须与Qualifier注解中设置的名字相同
@Service
public class UserServiceImpl implements UserService {
//@Autowired 默认按类型装配
@Autowired
@Qualifier("UserDao2")
private UserDao userDao;
@Override
public void save() {
userDao.save();
System.out.println("这是UserServiceImpl的save方法");
}
}
- 运行程序和案例1一样,直接放运行结果的截图。发现打印的是第二个实现类的方法
5.2@Resource
@Resource 注解是 Java EE 规范中提供的注解,它和 @Autowired 作用一样, 但@Resource 是按照名称注入引用类型,相当于 @Autowired + @Qualifier。
@Resource 相关属性:
name:设置注入的 bean 的 id 。type:设置注入的 bean 的类型,接收的参数为 Class 类型。
案例
//@Resource 按照名称装配
@Resource(name = "UserDao1", type = UserDaoImpl1.class)
private UserDao userDao;
5.3@Value
- 类型:属性注解、方法注解
- 位置:属性定义上方,方法定义上方。
- 作用:注入普通类型的属性。
- 说明:
- value 值仅支持非引用类型数据,赋值时对方法的所有参数全部赋值。
- value 值支持读取 properties 文件中的属性值,通过类属性将 properties 中数据传入类中,而且value 值支持 SpEL (先插个眼在这,明天的文章就会讲如何用注解读取properties配置文件)
- @value 注解如果添加在属性上方,可以省略 setter方法(和@Autowired一样)
案例
@Component("user")
public class User{
@Value("bighorn")
private String name;
}
写在后面🍻
感谢观看啦✨
有什么不足,欢迎指出哦💖
掘金的运营同学审核辛苦了💗