【Spring】之注解存取Bean对象

在本系列的上一篇文章中,我们已经了解了Spring的一些核心概念,并且还学习了Spring存取。但是我们发现在存取的过程中还是比较复杂,接下来我们将学习更为简单的Spring存取,其中涉及到的主要内容就是注解。并且在Spring家族的学习过程中,基本上注解是无处不在。

Spring项目的创建

a. 创建maven项目

【Spring】之注解存取Bean对象_第1张图片

b. 添加Spring框架依赖

将依赖放置于pom.xml中即可。


        
            org.springframework
            spring-context
            5.2.3.RELEASE
        

        
            org.springframework
            spring-beans
            5.2.3.RELEASE
        
    

c. 创建一个启动类

我创建的启动类是App类,其实本质上启动类没啥意义,就是为了测试写的代码是否正确。

【Spring】之注解存取Bean对象_第2张图片

Spring对象的存取

a. 配置扫描路径

想要成功的将对象存储在Spring中,我们就必须配置存储对象的扫描路径,只有扫描路径下的包,添加注解之后才可以被正确的识别并保存在Spring中。

扫描路径需要配置在resources下的xml中,xml需要自己创建。




b. 注解

在Spring存取的过程中,需要用到注解,因此先来写一下需要哪几个注解,为啥要有这么多的注解,每个注解的含义是啥。

在Spring存对象的过程中,有两种注解可以实现其功能,分别是五大类注解和方法注解

五大类注解

@Controller、@Service、@Repository、@Component、@Configuration。

@Controller

控制器,归属的是逻辑业务层,用户控制用户的行为,用来检查参数的有效性;通俗的讲,就是判断前端请求的合理性。

@Service

服务,归属的是服务层,调用持久化类来实现响应的功能,不直接和数据库交互,也不直接和前端请求交互,类似于控制中心;通俗的来说,就是中控,对前端的请求功能负责,然后来调配合适的数据库表。

@Repository

仓库,归属的是持久层,直接和数据库进行交互,通常每个表对应一个仓库;通俗的讲,就是一个库负责一个表的增删查改。

@Configuration

配置,归属的是配置层,用来配置当前项目的一些信息;通俗的说,对项目的全局配置负责。

@Component

组件,归属的是公共工具类,提供一些公共方法。

方法注解

@Bean,将当前修饰方法的方法对象存入到Spring中。

需要注意的一点就是@Bean注解必须要配合类注解来使用,否则就是无效的方法注解。

为啥要有这么多注解?

从本质上来说,五大注解的作用是一样的,都是将对象存入Spring中,那为啥还要有这么多的注解呢?从五大类注解的含义上来说,其作用就是分层,而不是一个类就将从前端接收过来的内容进行判断,改写最后给到数据库更改,而是一层一层,一层负责一件事,这样效率即提高了不少,还能增强代码的可更改性,减少“屎山代码”的出现。

对于上述注解的分层,大概是这样来区分的:首先前端接收到内容,将内容以一定的方式传给后端,后端在@Controller层接收内容,并在Controller层判断前端内容的合理性,然后将内容传给@Service层,此层作为一个中转层,接收@Controller层传过来的东西,再将东西传给@Repository,此层负责和数据库进行对接。这就是大致内容,然后另外两个注解就是负责其他的内容,等到碰见的时候做了解即可。

c. 添加注解存对象

使用五大注解

先简单的写一个内容来熟悉一下注解的作用,并且用启动类来看一下能否获取到结果。

首先就是将创建的包写入到扫描路径中,直接将下述代码置于配置文件中即可,必须要写配置文件,否则写了注解也无用。

【Spring】之注解存取Bean对象_第3张图片

将配置文件写好之后,就可以开始写主要内容了,还是实现一个简单的hello world吧,毕竟学习一个新的编程,最先开始学的就是如何输出hell world了。

package org.example.controller;

import org.springframework.stereotype.Controller;

@Controller
public class ArticleController {
    public String sayHello() {
        return "hello world";
    }
}

当有了配置文件并且也加了注解之后,其实内容就已经存储到Spring容器之中了,然后咋们来用启动类看一下结果吧。

package org.example;

import org.example.controller.ArticleController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        //获取Spring
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

        //获取Bean对象
        ArticleController articleController = context.getBean("articleController", ArticleController.class);

        //输出查看结果
        System.out.println(articleController.sayHello());
    }
}

【Spring】之注解存取Bean对象_第4张图片

到这里,大家已经会用注解来存储对象了。

如下图有一个问题就是我明明没写Bean对象的名称,为啥我使用了Bean对象的名称还不会报错?

这是因为在Spring中,默认Bean对象的名称就是将其类名的第一个字母小写。前提是类名书写规范的情况下,那么书写不规范呢?如果类名都是小写字母,那么就是使用类名就可以,如果第一个字母和第二个字母都是大写字母的话,那么也是使用类名获取。

使用方法注解

使用方法注解和使用类注解大致操作方法几乎一样,但是需要注意的就是使用方法注解时也必须要把类注解加上去,否则的话方法注解也没法使用。

也写一个简单的内容来看一下@Bean注解的作用吧,首先肯定是将类写入扫描路径中,但是我和类注解是在一个包下,因此不用配置,大家看一下自己的是否需要配置。

创建一个User类

在这里我使用了一个@Data注解,它的意思就是不用写set和get等各种方法,减少代码的冗余度,接下来有可能会写一个文章来专门介绍一个它,大家可以这样用,也可以写set和get方法。

package org.example.enity;

import lombok.Data;

@Data
public class User {

    private Integer id;
    private String username;
    private String password;

}

然后的话就是使用Bean注解了。

如下代码,搭配上了Controller注解来用,这些代码没啥真正的含义,就只是表示一下Bean注解的用处。

package org.example.controller;

import org.example.enity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {

    @Bean
    public User user() {
        User user = new User();
        user.setId(1);
        user.setUsername("王五");
        user.setPassword("123");
        return user;
    }

}

使用一个启动类来看一下结果。

public static void main(String[] args) {
        //获取Spring
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

        //获取Bean对象
        User user = context.getBean("user", User.class);

        //输出查看结果
        System.out.println(user);
    }

【Spring】之注解存取Bean对象_第5张图片

上述的Bean注解中,也可也给它一个名字,但是如果自己给了名字之后,就不能使用默认的名字了,并且好像默认的名字是和方法名一致,当然我不能太确定,只是自己做了一个简单实验验证了一小下。

@Bean(name = "user")

上述大致就是使用注解来存Bean对象的内容了。

d. 获取Bean对象

在上篇文章中,我们已经了解了先获取Spring对象再获取Bean对象的方法。接下来我们了解的不是使用注解来获取Bean对象,一般我们不会使用ApplicationContext和BeanFactory这两种方式,这虽然也能获取,但是使用注解是更好的方式,使用的注解是@Autowired和@Resource。

获取对象也叫做对象装配,意思是把对象取出来放到某个类中,有时候也叫做对象注入。

三大注入方式

属性注入、set注入、构造方法注入。

在注入方式的介绍中,要用到简单的分层,不然的话没办法演示这个注入效果。

【Spring】之注解存取Bean对象_第6张图片

如上图所示,三个类是咋们需要用到的类,两个类分层,然后App充当启动类,如果是在标准Web开发中,其本质就是前端,发送请求和接收请求;创建好之后,首先在spring-config.xml中将包名加上去,不然的话加上注解也毫无意义。

首先创建一个Service层。

package org.example.service;

import org.springframework.stereotype.Service;

@Service
public class CatService {
    public String sayHello() {
        return "hello 小猫!";
    }
}

然后创建一个Controller层。

这个就是简单的基本代码,只需要加入注入方式即可。

package org.example.controller;

import org.springframework.stereotype.Controller;

@Controller
public class CatController {
    
    public String sayHello() {
        return catService.sayHello();
    }
    
}

最后就是启动类了。

启动类的代码永远不用变,一直都是这个样子,只需要把这个controller层的代码写好即可。

public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

        CatController controller = context.getBean("catController", CatController.class);

        System.out.println(controller.sayHello());
    }
属性注入
@Autowired
private CatService catService;

属性注入的缺点:

功能性问题:无法注入一个不可变对象(final修饰的对象);

通用性问题:只能适用于IoC容器;

设计原则问题:更容易违背单一设计原则(针对对象是类)。

set注入
    @Autowired
    private CatService catService;
    public void setCatService(CatService catService) {
        this.catService = catService;
    }

和第一种方法相比,只是上述代码发生了改变。

它的优点就是更加符合单一设计原则(针对对象是方法级别);但是它的缺点也很明显:

不能注入不可变对象(即final修饰的对象);

注入的对象可被修改(由于setStudentService是普通方法,因此可以被重复调用,在重复调用的时候就存在被修改的风险)。

构造方法注入
    @Autowired
    private CatService catService;
    public CatController(CatService catService) {
        this.catService = catService;
    }

Spring推荐构造方法注入,使用构造方法注入@Autowired可以省略;适用于一个构造方法,如果有多个构造方法,那么不能省略。

其优点是:

可以注入不可变对象;

注入对象不会被修改(可以加上final修饰符;构造方法只是在类加载时执行一次,不像set,调用一次就执行一次,存在被修改的风险);

注入的对象会被完全初始化(使用构造方法带来的优点);

通用性更好。

两大注入注解

@Autowired、@Resource

相同点:都是用来进行获取Bean对象的,或者称为对象注入、或者也可也称为为依赖注入。

不同点:
Autowired是Spring提供的,而Resource则是JDK提供的;

Autowired可以实现三种注入方法,而Resource则不可以实现构造方法注入;

Autowired先根据名称获取,如果名称获取不到,才根据类型获取;Resource则是先根据类型获取,如果获取不到再根据名称获取;

Autowired支持required参数,而Resource则支持更多的参数,例如在一个典型的问题中:多个Bean对象类型相同获取报错,由于其没有按照规范写名称所致,如果使用Autowired注解的话,则需要多写一个@Qualifier(value = "")注解解决,但是在Resource注解中只需要加一个括号写入name即可。

总结

五大类注解和方法注解的了解;

三大注入方式和两大注入注解的了解。

更到这里,对于Spring的存取也就差不多了,最重要的也就是注解了,以后Spring中会一直使用,需要真正的理解其的作用接下来更的应该就是Bean对象的一些内容,然后就是SpringBoot等等。

你可能感兴趣的:(Spring系列,spring,java)