Spring 更简单的读取和存储对象

通过之前的学习,我们也能够实现基本的 Spring 读取和存储对象操作,感觉有点麻烦,接下来, 更简单的存储和读取对象的核心就是使用注解

1 存储 Bean 对象

1.1 配置扫描路径(重要)

先把依赖文件导入pom.xml:

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
    </dependencies>

接下来写入配置文件,名字最好起的有意义
在这里插入图片描述

把这串类容粘贴进去:

<?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">

    <!-- 配置 Spring 扫描的根路径(此根路径下的所有 Spring 存对象的注解才能生效) -->
    <content:component-scan base-package="beans"></content:component-scan>

</beans>

在这里插入图片描述

1.2 添加注解存储 Bean 对象

有两种注解类型可以实现:

1: 使用 5 大类注解实现:@Controller[控制器],@Service[服务],@Repository[仓库],
@Configuration[配置],Component[组件]

2: 通过方法注解: @Bean方法

1.2.1 类注解

① @Controller(控制器存储)
import org.springframework.stereotype.Controller;

@Controller
public class UserController {
    public void sayHi(String name){
        System.out.println("hello: "+name);
    }
}

在这里插入图片描述
在这里插入图片描述

后面解释原因.

② @Service(服务存储)
import org.springframework.stereotype.Service;

@Service
public class UserService {
    public void sayHi(String name){
        System.out.println("hello: "+name);
    }
}
③ @Repository(仓库存储)
import org.springframework.stereotype.Repository;

@Repository
public class UserRepository {
    public void sayHi(String name){
        System.out.println("hello: "+name);
    }
}
④ Configuration(配置存储)
import org.springframework.context.annotation.Configuration;

@Configuration
public class UserConfiguration {
    public void sayHi(String name){
        System.out.println("hello: "+name);
    }
}
⑤ Component(组件存储)
import org.springframework.stereotype.Component;

@Component
public class UserComponent {
    public void sayHi(String name){
        System.out.println("hello: "+name);
    }
}
测试读取 bean 的代码
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-config.xml");
        //Controller
        UserController userController = context.getBean("userController",UserController.class);
        userController.sayHi("Controller");

        //Service
        UserService userService = context.getBean("userService",UserService.class);
        userService.sayHi("Service");

        //Repository
        UserRepository userRepository = context.getBean("userRepository",UserRepository.class);
        userRepository.sayHi("Repository");

        //Configuration
        UserConfiguration userConfiguration = context.getBean("userConfiguration",UserConfiguration.class);
        userConfiguration.sayHi("Configuration");

        //Component
        UserComponent userComponent = context.getBean("userComponent",UserComponent.class);
        userComponent.sayHi("Component");
        
    }
}

在这里插入图片描述在这里插入图片描述

注意事项

1: 读取存入对象的 id 默认情况首字母是要小写的,大写读不到
在这里插入图片描述在这里插入图片描述

2: 当第一个字母和第二个字母都大写了,首字母小写就不能读到
在这里插入图片描述在这里插入图片描述这里就需要去观察源码是怎么实现的了,
双击shift搜索beanName
在这里插入图片描述在这里插入图片描述
它使⽤的是 JDK Introspector 中的 decapitalize ⽅法,源码如下在这里插入图片描述
像这种情况大写就行了
在这里插入图片描述

3: 包路径要写对
在这里插入图片描述

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

让代码的可读性更高,能够让程序员能够直观的判断当前类的用途

@Controller:表示的是业务逻辑层;
@Servie:服务层;
@Repository:持久层;
@Configuration:配置层;

程序的⼯程分层,调⽤流程如下:
在这里插入图片描述

类注解之间的关系

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

在这里插入图片描述
这几个注解都有一个注解@Component,说明了它们本身就是属于@Component"子类"

1.2.2 @Bean(方法注解)

类注解是添加到某个类上的,⽽⽅法注解是放到某个⽅法上的,如以下代码的实现:
先创建一个User类:

public class User {
    private int id;
    private String name;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    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;
    }
}

在创一个UserBean:

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

@Component
public class UserBean {

    @Bean
    public User user(){
        User user = new User();
        user.setId(1);
        user.setName("张三");
        return user;
    }
}

测试读取的内容:

import beans.User;
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-config.xml");
        User user = context.getBean("user",User.class);
        System.out.println(user.toString());
    }
}

在这里插入图片描述

注意要有类注解,不然获取不到:
在这里插入图片描述

如果不加类注解:
在这里插入图片描述

方法重命名

可以通过设置 name 属性给 Bean 对象进⾏重命名操作,如下代码所示:

在这里插入图片描述

@Bean 命名规则,当没有设置 name 属性时,那么 bean 默认的名称就是方法名,当设置了name 属性之后,只能通过重命名的 name 属性对应的值来获取,也就是说重命名之后,在使用方法名就获取不到 bean 对象
在这里插入图片描述

他也可以重命名多个:
在这里插入图片描述

2. 获取 Bean 对象(对象装配)

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

对象注入(对象装配)[从容器中将对象读取出来]三种方式:

  • 属性注入(字段注入)
  • 构造方法注入
  • Setter注入

2.1 属性注入

属性注入使用 @Autowired 实现的,我们来将 Service 类注入到 Controller 类中:
Service:

import org.springframework.stereotype.Service;

@Service
public class UserService {
    public void sayHi(){
        System.out.println("hello,Service!");
    }
}

Controller:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    public void sayHi(){
        userService.sayHi();
    }
}

App启动:

import beans.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App2 {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        UserController userController = context.getBean(UserController.class);
        userController.sayHi();
    }
}

在这里插入图片描述

2.2 构造方法注入

构造⽅法注⼊是在类的构造⽅法中实现注⼊
在这里插入图片描述

2.3 Setter注入

Setter 注⼊和属性的 Setter ⽅法实现类似,只不过在设置 set ⽅法的时候需要加上 @Autowired 注解

在这里插入图片描述

注:如果当前类里构造方法只有一个, 那么@Autowired是可以被省略的

三种注入优缺点分析

属性注入:
优点就是简洁,使用方便;
缺点通用性不好,只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指针异常)

构造方法(官方推荐):
它的缺点是如果有多个注⼊会显得⽐较臃肿,但出现这种情况你应该考虑⼀下当前类是否符合程序的单⼀职责的设计模式了,它的优点是通⽤性好,在使⽤之前⼀定能把保证注⼊的类不为空

Setter注入:
Setter ⽅式是 Spring 前期版本推荐的注⼊⽅式,但通⽤性不如构造⽅法,所有 Spring 现版本已经推荐使⽤构造⽅法注⼊的⽅式来进⾏类注⼊了

2.4 @Resource: 另一种注入关键字

在进⾏类注⼊时,除了可以使⽤ @Autowired 关键字之外,我们还可以使⽤ @Resource 进⾏注⼊,注意一点的是,@Resource 无法进行构造方法注入

属性注入:
在这里插入图片描述

Setter注入:
在这里插入图片描述

构造方法注入就不行:
在这里插入图片描述

@Autowired 和 @Resource 的区别

1: 出身不同: @Resource 来自于 JDK(Java 亲儿子),@Autowired 是 Spring 框架提供的

2: 用法不同: @Autowired 支持属性注入,构造方法注入,Setter注入,而 @Resource 不支持构造方法注入

3: 支持的参数不同: @Resource 支持更多的参数设置,比如 name,type 设置,而@Autowired 只支持required 参数设置

同一个类型多个 @Bean 报错

在这里插入图片描述

报错的原因就是非唯一的 Bean 对象

解决办法:

1: 精确的描述 bean 的名称(将注入的名称写对)
在这里插入图片描述

2: 使用@Resource 设置 name 的方式 来重命名注入对象(如果已经写太多不想改了就可以用这种方式)
在这里插入图片描述注: @Atowired不能这样设置
在这里插入图片描述

3: 使用 @Qualifier来筛选bean对象(@Atowired@Resource都可以)
在这里插入图片描述
在这里插入图片描述

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

粉色的志明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值