3

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解bean...

 1 year ago
source link: https://blog.51cto.com/panyujie/5487208
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName

推荐 原创

如何更简单的储存spring

在 Spring 中想要更简单的存储和读取对象的核⼼是使⽤注解,也就是我们接下来要学习 Spring 中的相关注解,来存储和读取 Bean 对象。

  1. 创建一个maven文件
  2. 添加spring核心包
  3. 配置xml文件,在文件中配置扫描路径
  4. 在代码中直接使用注解读取和储存

以前需要在储存一个bean对象时,需要手动的在配置文件中创建bean,这里直接配置一个扫描路径,将所有需要储存的对象放到该目录下当我们用在代码中用注解标识该类时,spring会自动的扫描这个路径,将对应的对象自动添加到spring框架中。


1、前置⼯作:配置扫描路径(重要)

在使用注解之前,我们需要配置扫描路径,将所有的对象直接放在该路径下,spring会自动扫描对应的bean并添加到框架中

创建一个xml配置文件:

<?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="model"></content:component-scan>
    
</beans>

这里的base-package属性中写入对象存放的路径,这里是放在了model包下。

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_类注解

也就是说,即使添加了注解,如果不是在配置的扫描包下的类对象,也是不能被存储到 Spring 中的。

配置完成后,就可以使用注解了。


2、添加注解存储 Bean 对象

想要将对象存储在 Spring 中,有两种注解类型可以实现:

  1. 类注解
  • @Controller
  • @Service
  • @Repository
  • @Component
  • @Configuration
  1. ⽅法注解
  • @Bean
【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_方法注解_02

接下来我们分别来看。


1. 类注解:

问:Spring是如何知道需要将哪些Javal类注册到容器中?

使用配置文件或者注解的方式来标识需要处理的Java类

类注解也可以称为组件类注解,即把一些类当做组件进行使用。

  1. @Component标识一个普通的bean类
  2. @Controller标识一个控制器组件类,一般用在控制前后端交互的类中,进行数据校验。
  3. @Service :标识一个业务逻辑组件类,进行数据的组装。
  4. @Repository标识一个DAO组件类,即数据访问层组件,用来访问数据,像连接数据库,进行增删查改操作。
  5. @Configuration标识一个类作为加载spring的配置类,这个类的作用是配置spring并启动spring容器。

类注解之间的关系

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_Bean_03

@Component、@Controller、@Service、@Repository这四个注解实际上一类注解,功能相同,用法相同,区别在于标识当前类是什么组件类型,方便程序员快速了解当前类的作用。

@Component可以替代@Controller、@Service、@Repository,因为这三个注解是被@Component标注的,从逻辑上可以理解为是Component的子类

如下图:
Controller、Service、Repository三者都是被Component标注。

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_spring_04

① @Controller(控制器存储)

使⽤ @Controller 存储 bean 的代码如下所示:

package model;

import org.springframework.stereotype.Controller;

@Controller //将当前类储存到Spring,标识此类为控制交互层
public class UserController {
    public void firstUseController(String name){
        System.out.println("Hi,Controller:"+name);
    }
}

在测试类中使用:

读取对象的⽅式来读取上⾯的 UserController 对象

import model.HelloApplicationContext;
import model.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
     
     ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
     
     //
     UserController userController=(UserController) context.getBean("userController");
        
     userController.firstUseController("Hello!");
        
    }
}

输出结果:

Hi,Controller:Hello!

注意事项:

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_spring_05

② @Service(服务存储)

使⽤ @Service 存储 bean 的代码如下所示:

package model;

import org.springframework.stereotype.Service;

@Service //将此类储存到String中,这个类中可以进行数据组装
public class UserService {
    public void firstUseService(String name){
        System.out.println("Hi,Service:"+name);
    }
}

在测试类中读取 bean

import model.HelloApplicationContext;
import model.UserController;
import model.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        
      ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        
      UserService userService=(UserService) context.getBean("userService");
        
      userService.firstUseService("Hello!");
        
    }
}

输出:

Hi,Service:Hello!

③ @Repository

package model;

import org.springframework.stereotype.Repository;

@Repository//将此类储存到String中,标识此类是数据访问组件
public class UserRepository {
    public void firstUseRepository(String name){
        System.out.println("Hi,Repository:"+name);
    }
}

在测试类中使用:

import model.HelloApplicationContext;
import model.UserController;
import model.UserRepository;
import model.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
      ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
      UserRepository userRepository=(UserRepository) context.getBean("userRepository");
      userRepository.firstUseRepository("Hello!");
    }
}
Hi,Repository:Hello!

④ @Component

package model;

import org.springframework.stereotype.Component;

@Component 
public class UserComponent {
    public void firstUseComponent(String name){
        System.out.println("Hi,Component:"+name);
    }
}

在测试类中使用:

import model.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
      ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
      UserComponent userComponent=(UserComponent) context.getBean("userComponent");
      userComponent.firstUseComponent("Hello!");
    }
}
Hi,Component:Hello!

  • 被注解的Java类会被当做Bean对象储存到spring中,这个对象的默认名称是类名的首字母小写,其余部分不变。
【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_java_06
  • @Service也可以自定义Bean名称,但是必须唯一
  • 尽量使用对应的组件注解来替换@Component,因为未来的Spring版本中,@Controller,@Service,@Repository可能会携带更多语义

2. 方法注解

@Bean

方法注解:

@Bean注解在方法前,作用是让这个方法产生一个Bean对象,然后这个Bean对象交给容器进行管理。这个方法只会spring只会调用一次,然后将这个对象放入自己的IOC容器中。

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_Bean_07
package model;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class UserBean {
    private String name;
    private int Id;
    private int age;
    public void setName(String name) {
        this.name = name;
    }
    public void setId(int id) {
        Id = id;
    }
    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "UserBean{" +
                "name='" + name + '\'' +
                ", Id=" + Id +
                ", age=" + age +
                '}';
    }

    @Bean
    public UserBean users(){
        UserBean user=new UserBean();
        user.setName("张三");
        user.setId(01);
        user.setAge(18);
        return user;
    }
}

在测试类中运行:

import model.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.jws.soap.SOAPBinding;

public class App {
    public static void main(String[] args) {
        //1.获取上下文对象
      ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
      //2.获取spring中存入的bean对象,id默认是类名首字母小写,其余不变
       UserBean user=(UserBean)context.getBean("users");
       //3.调用方法
        System.out.println(user.toString());
    }
}

运行结果如下:

UserBean{name='张三', Id=1, age=18}

注意:

Spring在默认情况下是类扫描,如果使用方法注解@Bean,需要搭配类注解@Component或者@Configuration一起使用,否则spring无法扫描到这个方法,就不能将方法返回对象储存到spring中。


@Bean 重命名

在使用@Bean时,我们可以对方法进行重命名,可以同时为该方法创建多个名字

这个重命名的 name 其实是⼀个数组,⼀个 bean 可以有多个名字

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_spring_08
    @Bean(name={"u1","userinfo1"})
    public UserBean users(){
        UserBean user=new UserBean();
        user.setName("张三");
        user.setId(1);
        user.setAge(18);
        return user;
    }

当创建了多个名字后,原来的方法名就失效,我们可以使用重命名来获取bean对象。

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_java_09

为什么要有这么多 类注解?

这和为什么每个省/市都有⾃⼰的⻋牌号是⼀样的?

⽐如陕⻄的⻋牌号就是:陕X:XXXXXX,北京的⻋牌号:京X:XXXXXX,⼀样。甚⾄⼀个省不同的县区也是不同的,⽐如⻄安就是,陕A:XXXXX,咸阳:陕B:XXXXXX,宝鸡,陕C:XXXXXX,⼀样。这样做的好处除了可以节约号码之外,更重要的作⽤是可以直观的标识⼀辆⻋的归属地

那么为什么需要怎么多的类注解也是相同的原因,就是让程序员看到类注解之后,就能直接了解当前类 的⽤途,⽐如:

  • @Controller:表示的是业务逻辑层;

  • @Servie:服务层;

  • @Repository:持久层;

  • @Configuration:配置层

程序的⼯程分层,调⽤流程如下:

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_spring_10

类注解之间的关系?

查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_类注解_11

其实这些注解⾥⾯都有⼀个注解 @Component说明它们本身就是属于 @Component 的“⼦类”


Spring 如何制作出类注解的 beanName?

通过上⾯示例,我们可以看出:

通常我们 bean 使⽤的都是标准的⼤驼峰命名

读取的时候⾸字⺟⼩写就可以获取到 bean 了,如下图所示:

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_java_12

然⽽,当我们⾸字⺟和第⼆个字⺟都是⼤写时,就不能正常读取到 bean 了,如下图所示:

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_java_13

如果使用原名就又可以读取了,这是为什么呢?

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_spring_14

这个时候,我们就要查询 Spring 关于 bean 存储时⽣成的命名规则了

我们可以在 Idea 中使⽤搜索关键字 beanName 可以看到以下内容:

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_spring_15

顺藤摸⽠,我们最后找到了 bean 对象的命名规则的⽅法

它使⽤的是 JDK Introspector 中的 decapitalize ⽅法,源码如下:

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_方法注解_16

所以对于上⾯报错的代码,我们只要改为以下代码就可以正常运⾏了:

【Spring】Spring 用注解 储存bean(类注解、方法注解)、Spring如何制作出类注解beanName_方法注解_17

  • 打赏
  • 1
  • 1收藏
  • 评论
  • 分享
  • 举报

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK