java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring存对象和取对象

Spring中存对象和取对象的方式详解

作者:it小婷

这篇文章主要介绍了Spring中存对象和取对象的方式,Spring中更简单的存对象与取对象的方式是注解,注解实现有两种方式:一在编译的时候,把注解替换成相关代码,并添加到我们原来的代码中,二拦截方法,文中有详细的代码示例供大家参考,需要的朋友可以参考下

本文我来介绍一种更简单的存储对象方式和取对象方式,跟上我的节奏,我们开始吧!!

透露一下:Spring中更简单的存对象与取对象的方式是注解。

给大家插个题外话(了解即可),注解实现有两种方式:1.在编译的时候,把注解替换成相关代码,并添加到我们原来的代码中。2.拦截方法,当程序执行到某个方法时,会执行拦截,在执行之前或之后或之中进行一些操作(与我们写的注解有关)。

1.存储对象(Bean)

在上一篇我们存储对象是在配置文件中添加<bean>标签,但这样其实很麻烦,我们每次都得去那添加一个。所以为了简化,我们可以在配置文件中配置扫描路径,然后通过注解来存储对象。

1.1配置扫描路径(重要!!!)

在使用的时候,把下面这段代码放到你的配置文件中,把<content>标签中的包名替换成你项目需要扫描的包名。(这个搭配注解来实现存储对象)

<?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:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <content:component-scan base-package="包名"></content:component-scan>
</beans>

为什么会配置这个扫描路径呢?举个例子吧,假设你找个人,你是从整个中国一个一个找好找还是从一个村里找好找。所以嘛,Spring也是这样呀,你给它配置了扫描包,Spring就会从这个包里一个一个找,看哪些添加了注解(需要Spring帮忙创建对象的),他就会把哪些类存储起来。

1.如果我们配置的扫描包中存在子类,里面的注解也是会被扫描的。

2.如果我创建的类在扫描包外面,此时我用相关注解也没有用的,因为根本不会扫这个类!

3.那如果我的类就是在扫描包外面,但是欸,我还是想交给Spring创建对象,肿么办呢?好说嘛!用我上一篇存储Bean的方法,扫描包可以与Bean同时生效的。

4.我们设置了扫描包,没有添加注解,这样也是没办法将对象存储到Spring中的。(两个要搭配使用!!!)

1.2添加注解存储对象

将对象存储到Spring中,有两种可以实现,一种是类注解,一种是方法注解。

1.2.1类注解

类注解有五种:@Controller @Service @Component @Repository @Configuration。

我先来说一下,为啥有这么多类注解。简单来说,为了让程序员看到类注解后更直观的知道这个类是干什么的。JavaEE上有标准分层(至少三层):控制层,业务层,数据层。当然也有更多层的划分,大家可以看阿里巴巴Java开发手册。

控制层主要用于与用户交互,业务层主要用于处理一些业务,数据层主要与数据库进行交互。不同层干不同事,所以也就出来了不同的注解。

1.2.1.1@Controller

这个注解主要用于控制层中。代码如下:

@Controller//通过这个注解将对象存储到Spring中
public class StudentController {
    public void study() {
        System.out.println("控制层aaaa");
    }
}

1.2.1.2@Service

这个注解一般都是用于业务层的。

@Service//通过这个注解存储对象
public class StudentService {
    public void eat() {
        System.out.println("业务层啊啊啊");
    }
}

1.2.1.3@Repository

这个注解用在Dao层,也即是数据层。

@Repository
public class StudentMapper {
    public void study() {
        System.out.println("我是数据层");
    }
}

1.2.1.4@Component

这个用于哪呢?当我们进行一些操作不属于三层中的任何一层的时候,我们就可以用这个注解。

@Component
public class Test {
    public void test() {
        System.out.println("保密功能");
    }
}

1.2.1.5@Configuration

这个一般都是用于配置类上。

@Configuration
public class Test1 {
    public void set() {
        System.out.println("配置类");
    }
}

1.2.1.6五大类注解的关系

这五大类注解其实本质都一样,都是为了将对象存储到Spring中。并且@Controller / @Service / @Repository / @Configuration这几个的源码中都存在@Component,可以认为这四个注解均为@Component的子类,或者均为@Component的扩展。

1.2.1.7通过类注解将对象存储到Spring中的命名规则

  1. 当我们创建的类名为比较标准的大驼峰形式,Spring提供的对象名为首字母小写,其余不动的形式。
  2. 如果类名首字母和第二个字母都为大写,提供的对象名为原类名。
  3. 除了第二条外,默认情况下都是Spring提供的对象名为首字母小写,其余不动的形式。

1.2.2方法注解

1.2.2.1使用与注意事项

方法注解为@Bean。顾名思义,该注解用到方法上。

创建一个User类,并且创建一个Users类,我们来使用一下。

//User类
public class User {
    private int id;
    private String name;
    private int age;
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
}
 
 
 
//Users类
 
@Component
public class Users {
    @Bean
    public User user1() {
        User user = new User();
        user.setAge(18);
        user.setName("张三");
        user.setId(1);
        return user;
    }
}

注意事项:

1.@Bean注解必须搭配五大类注解使用,否则会报错的!(为了Spring执行的性能)

2.通过方法注解将对象存储到Spring中命名规则为(默认情况下)对象名等于方法名。

3.方法的返回类型必须存在,且必须为一个类。

4.我们可能不同类却存在相同方法名的方法,此时如果我们仍采用方法名作为对象id来获取对象,此时会出现覆盖。最后只有一个结果,而且还不一定是我们想要拿到的那个对象。我们有两种方法进行解决:一种是通过注解@Order注解来给其排序,值越小的优先级越高,越先执行。(但是也会覆盖)最后呈现的结果为值最大的。另外一种是给Bean重命名。

5.当我们对同一类型使用多个@Bean时,通过注入的方式注入对象会报错的,因为有多个Bean了,Spring不知道用哪个了。有两种解决方法:(1)注入的时候,使用Resource注解,并且指定对象名,通过name属性;(2)使用@Qualifier注解的value属性来设置注入的名称(必须结合Autowired使用)。

1.2.2.2Bean重命名

由于上面我们提到了当用默认的提供名字的时候可能会出现误差,所以我们可以对方法上面的@Bean进行重命名。说白了也就是对存储到Spring种的对象指定好名字。

//可以只指定一个名字
    
@Bean(name = "user")//这里可以用name=...也可以用value=.....
    public User user1() {
        User user = new User();
        user.setAge(18);
        user.setName("张三");
        user.setId(1);
        System.out.println(1);
        return user;
    }
 
 
//也可以指定多个名字(用哪个都可以)
 
 
@Bean(name = {"user","use","custom"})//这里可以用name=...也可以用value=.....
    public User user1() {
        User user = new User();
        user.setAge(18);
        user.setName("张三");
        user.setId(1);
        System.out.println(1);
        return user;
    }

但是,当我们重命名以后,就不可以再用方法名(Spring默认提供的名字)来取出对象了,除非你将重命名后的名字设置为了方法名。

2.取出对象

我在上一篇文章中,叙述了取出对象的方法,正常来说,我们仍这样去取出最终对象。但是在一些类中用到另外的类的时候,我们可以有简单方法呀,也就是对象注入。

对象注入有三种方式:属性注入;setters方法注入;构造方法注入。

@Autowired是先通过类型进行查找,如果发现有多个,然后通过名称(根据我们定义的属性后面,我们定义的变量名查找)查找。(装配顺序)

@Qualifier必须和@Autowired一起使用,@Qualifier通过名字来进行注入。

@Resource先根据名称(如果有多个相同的名称)查再根据类型查。
@Value注入普通类型属性。

2.1属性注入 

@Controller
public class StudentController {
    @Autowired
    public StudentService studentService;//在控制类中引入了另外一个类,为了更方便使用,我们这里采用对象注入方式注入对象。
    public void study() {
        System.out.println("控制层aaaa");
    }
}

属性注入就是通过@AutoWired注解来完成的。将这个注解放在当前类中引入的另外类最为成员变量的上面即可。

优点:很简单。

缺点:

1.对于有final修饰的变量无法无法进行注入。

2.兼容性差,只使用于IoC容器。

3.风险更大,更容易违背单一设计原则。(比如在服务层,我们就想处理一套业务,但通过这个我们可以进行多套业务)

2.2setters方法注入

也就是通过setters方法进行注入

@Controller
public class StudentController {
    private StudentService studentService;
 
//添加setter方法,并添加注解(注入对象)
@Autowired
    public void setStudentService(StudentService studentService) {
        this.studentService = studentService;
    }
 
 
    public void study() {
        System.out.println("控制层aaaa");
    }
}

优点:符合单一设计规则,每个Setter方法只有一个参数。

缺点:

1.不能注入不可变对象(final修饰的)

2.使用setter注入的对象可能被修改。

2.3构造方法注入

也就是通过构造方法来注入对象。

@Controller
public class StudentController {
    private StudentService studentService;
//通过构造方法来注入了
 
@Autowired
    public StudentController(StudentService studentService) {
        this.studentService = studentService;
    }
 
 
 
    public void setStudentService(StudentService studentService) {
        this.studentService = studentService;
    }
 
    public void study() {
        System.out.println("控制层aaaa");
    }
}

1.如果当前类只有这样的一个构造方法,@Autowired这个注解是可以省略的。

优点:

1.可以注入不可变对象(final修饰的)为什么呢?因为被final修饰的变量必须被复制,要不直接复制,要不就是在构造方法中复制。

2.注入对象不会被改变的,构造方法只会执行一次。

3.构造方法注入可以保证完全被初始化。

4.通用性更好。

2.4另外种注入关键字@Resource

和@Autowired相同之处:

不同之处:

以上就是Spring中存对象和取对象的方式详解的详细内容,更多关于Spring存对象和取对象的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文