写点什么

【Spring 学习笔记 (八)】Spring IoC/DI 注解开发 之 原始注解开发

作者:倔强的牛角
  • 2022 年 6 月 09 日
  • 本文字数:3796 字

    阅读完需:约 12 分钟

【Spring 学习笔记(八)】Spring IoC/DI注解开发 之 原始注解开发

写在前面😘

大一电子信息工程新生,请多多关照,希望能在 InfoQ 社区记录自己的学习历程!

【Spring 学习笔记】 系列教程基于 Spring 5.2.10.RELEASE讲解 。

一、注解开发简介

有关 Spring IoC 的 xml 文件配置开发终于介绍了,但是感觉写配置文件好麻烦,没体验到 Spring 简化开发的过程啊。

其实,要想真正简化开发,害得用到 Spring 的注解开发。

接下来,就让大牛角来讲解 Spring 注解开发吧!

1、什么是注解开发

指的是在类或者方法上加入特定的注解(@XXX),完成特定功能的开发。


@Componentpublic class XXX{}
复制代码

2、spring 注解开发历程

  1. Spirng2.x 开始支持注解开发 @Component 等目的:起初,只是为了简化 XML 的配置,作为 XML 的有益补充

  2. Spring3.x 纯注解开发@Configuration 等目的:彻底替换 XML,基于纯注解开发

  3. 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 作用,细节以及用法完全一致


目的:更加准确的表达一个类型的作用。

示例👇
/*创建web层对象**/@Controllerpublic class UserController {    ...}/*创建service层对象**/@Servicepublic class UserServiceImpl implements UserService {    ...}/*创建dao层对象**/@Repositorypublic 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 示例👇

  1. 如果你使用的 JDK 是 9 以后的,你可能需要先导入javax.annotation包,才能使用生命周期相关注解。


<dependency>    <groupId>javax.annotation</groupId>    <artifactId>javax.annotation-api</artifactId>    <version>1.3.2</version></dependency>
复制代码


  1. 定义初始化方法和销毁方法,并在方法上方添加相关注解。


@Componentpublic 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>
复制代码


  1. 编写运行程序


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();}
复制代码


  1. 运行结果如下


5、Bean 属性注入注解

5.1@Autowired、@Qualifier

  • 类型:属性注解、方法注解

  • 位置:属性定义上方,也可以是方法定义上方。

  • 作用:引用类型注入

  • 说明:@Autowired 默认按类型装配指定 @Qualifier 后则可以指定装配的 bean 的 id

  • 相关属性:

  • required:定义该属性是否允许为 null 。

  • 注意:@Qualifier 不能独立使用,必须和 @Autowired 一起使用

案例 1:按照 Bean 类型注入
  1. 编写 dao 层实现类


@Repositorypublic class UserDaoImpl implements UserDao {    @Override    public void save() {        System.out.println("这是UserDaoImpl的save方法");    }}
复制代码


  1. 编写 service 层实现类,在成员属性 userDao 上面添加@Autowired注解,spring 就会自动根据 UserDao 这个类型去找相应的 bean 注入。


  • 注意:@Autowired 可以写在属性上,也可也写在 setter 方法上,最简单的处理方式是写在属性上并将setter方法删除掉


@Servicepublic class UserServiceImpl implements UserService {    //@Autowired 默认按类型装配    @Autowired    private UserDao userDao;
@Override public void save() { userDao.save(); System.out.println("这是UserServiceImpl的save方法"); }}
复制代码


  1. 编写运行程序


public static void main(String[] args) {    //获取IoC容器    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");    //从容器中获取对象    UserServiceImpl userService = context.getBean(UserServiceImpl.class);    //调用save方法    userService.save();}
复制代码


  1. 运行结果如下👇


案例 2:按照 Bean 名称注入

案例 1 已经验证了 @Autowired 是按照类型注入,但如果 UserDao 接口有多个实现类:UserDaoImpl2、UserDaoImpl3、UserDaoImpl4。。。


此时,按照类型注入就无法区分到底注入哪个对象,解决方案:按照名称注入,指定 @Qualifier 后则可以指定装配的 bean 的 id。


  1. 编写多个 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方法"); }}
复制代码


  1. 编写 service 层实现类,在成员属性 userDao 上面添加@Autowired注解,并使用@Qualifier(" ")指定要注入的 bean。


注意点


  • AutoWired 注解基于类型进行注入注入对象的类型,必须与目标成员变量类型相同或者是其子类(实现类)

  • AutoWired 配合 Qualifier 注解基于名称进行注入,注入对象的 id 值必须与 Qualifier 注解中设置的名字相同


@Servicepublic class UserServiceImpl implements UserService {    //@Autowired 默认按类型装配    @Autowired    @Qualifier("UserDao2")    private UserDao userDao;
@Override public void save() { userDao.save(); System.out.println("这是UserServiceImpl的save方法"); }}
复制代码


  1. 运行程序和案例 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;}
复制代码

写在后面🍻

感谢观看啦✨

有什么不足,欢迎指出哦💖

发布于: 刚刚阅读数: 4
用户头像

把学问造就,还期身健行优。 2022.06.02 加入

大一在读,电子信息工程专业。 希望在InfoQ写作社区记录自己的学习历程!

评论

发布
暂无评论
【Spring 学习笔记(八)】Spring IoC/DI注解开发 之 原始注解开发_Java_倔强的牛角_InfoQ写作社区