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

1.存储Bean对象

之前我们存储Bean时,需要在spring-config中添加一行bean注册内容才行,而现在我们只需要一个注解就可以代替之前要写的一行配置了

1.1前置工作:配置扫描路径(重要)

在spring-config.xml中添加如下配置:



    

其中标签为注册扫描的包,它会自动是被这个包下面的bean,并将其存储到Spring中。

1.2添加注解存储Bean对象

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

  1. 类注解:@Controller、@Service、@Respository、@Component、@Configuration
  2. 方法注解:@Bean

【类注解使用方法】

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

这样就将UserController存储到Spring中了。

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

类注解的功能基本是一样的,都是在类的前面进行注释,就能将相应的类存储到Spring中。但是功能相同,为什么还要这么多种注解呢?

这就是为了让程序员看到类注解之后,就能直接了解当前类的用途了。比如:

  • @Contorller:表示业务逻辑层
  • @Service:表示服务层
  • @Repository:表示数据持久层
  • @Configuration:表示配置层

程序的工程分层,调用流程如下:

Spring更简单的读取和存储对象_第1张图片

 1.3.1Bean的命名规则

我们已经知道如何存储一个Bean,但是我们应当如何使用呢?

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

通过上面的示例,我们可以看出,bean使用大驼峰的形式命名,而在取出的时候我们使用小驼峰的形式。

我们看一下里面的源码。我们双击Spring搜索关键字:beanName

Spring更简单的读取和存储对象_第2张图片

Spring更简单的读取和存储对象_第3张图片

 我们发现它是使用JDK中的方法。命名规则如下:

  • 名字长度大于1,第一个字母为大写和第二个字母为大写,返回原来的类名;
  • 其他情况,返回第一个字母为小的名字

1.4方法注解@Bean

类注解是添加到类上面的,而方法注解是添加到方法上面的,代码实现如下:

package com.bit.service.model;

import org.springframework.context.annotation.Bean;

/**
 * Describe:
 * User:lenovo
 * Date:2023-07-20
 * Time:11:19
 */
public class Uses {
    @Bean
    public User user1() {
        User user = new User();
        user.setId(1);
        user.setName("Java");
        return user;
    }
}
package com.bit.service.model;

/**
 * Describe:
 * User:lenovo
 * Date:2023-07-20
 * Time:11:19
 */
public class User {
    private int Id;
    private String name;

    public int getId() {
        return Id;
    }

    public void setId(int id) {
        Id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 我饿们尝试去获取上面的Bean对象:

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        User user = context.getBean("user1", User.class);
        System.out.println(user);
    }

Spring更简单的读取和存储对象_第4张图片

 我们来探究以下原因。

1.4.1方法注解要配合类注解使用

由于一个程序中有很多的类,所有了的方法更是不计其数,如果所有方法都要扫描,效率会大大降低,方法注解要配合着类注解来使用,这样就能提高效率。代码如下:

@Component
public class Uses {
    @Bean
    public User user1() {
        User user = new User();
        user.setId(1);
        user.setName("Java");
        return user;
    }
}

我们再次尝试获取Bean,这次就成功了。

Spring更简单的读取和存储对象_第5张图片

 1.4.2重命名Bean

我们可以通过设置name属性给Bean对象进行重新命名的操作,代码如下:

@Component
public class Uses {
    @Bean(name = "user")
    public User user1() {
        User user = new User();
        user.setId(1);
        user.setName("Java");
        return user;
    }
}
   public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        User user = context.getBean("user", User.class);
        System.out.println(user);
    }

这个重命名的name实际上是一个数组,一个bean可以有多个名字:

@Component
public class Uses {
    @Bean(name = {"user", "user1", "u1"})
    public User user1() {
        User user = new User();
        user.setId(1);
        user.setName("Java");
        return user;
    }
}
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        User user = (User)context.getBean("u1");
        System.out.println(user);
    }

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

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

对象装配(对象注入)的实现方法以下3中:

  1. 属性注入
  2. 构造方法方法注入
  3. Setter注入

2.1属性注入

属性注入是使用 @Autowired 实现的,将 Service类注入到 Controller类中。

Service类的代码如下:

@Service
public class UserService {
    /**
     * 根据ID获取用户数据
     *
     */
    public User getUser(Integer id) {
        //伪代码
        User user = new User();
        user.setId(id);
        user.setName("Java-" + id);
        return user;
    }
}

Controller类的代码如下:

@Controller
public class UserController {
    //属性注入
    @Autowired
    private UserService userService;

    public User getUser(Integer id) {
        return userService.getUser(id);
    }

    public void sayHi(String name) {
        System.out.println("Hi," + name);
    }
}

获取Controller中getUser方法:

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserController userController = context.getBean("userController", UserController.class);
        System.out.println(userController.getUser(1).toString());
    }

Spring更简单的读取和存储对象_第6张图片

 这里的关键是我们没有在UserController中创建UserService对象而是使用属性注入的方式直接获取到了这个对象。

Spring更简单的读取和存储对象_第7张图片

 2.2构造方法注入

构造方法注入式是在类的构造方法中实现注入,如下代码所示:

@Controller
public class UserController2 {
    private UserService userService;

    //构造方法注入
    @Autowired
    public UserController2(UserService userService) {
        this.userService = userService;
    }

    public User getUser(Integer id) {
        return userService.getUser(id);
    }
}

【注意】只有一个构造方法时,那么 @Autowired注解可以省略

但是如果类中有多个构造方法,那么需要添加上@AutoWired来明确指定到底使用哪一个构造方法,否则将会程序报错。

2.3Setter注入

代码如下:

@Controller
public class UserController3 {
    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public User getUser(Integer id) {
        return userService.getUser(id);
    }
}

【使用方法】

public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
        UserController3 userController3 = applicationContext.getBean("userController3", UserController3.class);
        System.out.println(userController3.getUser(1).toString());
    }

2.4三种注入优缺点分析

  • 属性注入的优点是简洁使用方便;缺点是只能在IoC容器,如果是非IoC容器不可用,并且只有在使用的时候才会出现空指针异常。
  • 构造方法注入是Spring推荐的注入方法,它的确定是如果有多个注入会显得比较臃肿,但出现这种情况就表示当前类不符合程序的单一职责的设计模式,它的优点是通用性,在使用之前一定能把保证的类不为空。
  • Setter方式是Spring前期版本推荐的注入方法,但是通用性不如构造方法,并且可能存在直接调用Setter方法的情况。

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

在进行类注入时,除了可以使用@Autowired关键字之外,我们还可以使用@Resource进行注入。

@Autowried 和 @Resource的区别

  • 出身不同:@Autowired来自Spring,而@Resource来自JDK的注解;
  • 使用时设置的参数不同:相对于@Autowired来说,@Resource支持更多的参数设置
  • @Autowired可用Setter注入、构造函数注入和属性注入,而@Resource只能用于Setter注入和属性注入,不能使用构造方法注入。

2.6同一个类型多个@Bean报错

当出现以下多个Bean的时候,饭hi同一个类型时程序就会报错,如下代码:

@Component
public class Uses {
    @Bean()
    public User user1() {
        User user = new User();
        user.setId(1);
        user.setName("Java");
        return user;
    }
    
    @Bean
    public User user2() {
        User user = new User();
        user.setId(2);
        user.setName("MySQL");
        return user;
    }
}

此时我们使用属性注入

@Controller
public class UserController4 {
    @Autowired
    User user;

    public void func() {
        System.out.println(user);
    }
}

使用这个类

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserController4 userController4 = context.getBean("userController4", UserController4.class);
        userController4.func();

    }

Spring更简单的读取和存储对象_第8张图片

 同一类型多个Bean报错处理

  • 使用@Resource(name="user1")定义
  • 使用@Qualifier(value = "user1)注解定义名称。

Spring更简单的读取和存储对象_第9张图片

3.综合练习

在Spring项目中,通过main方法获取到Controller类,调用Controller里卖弄通过注入的方式调用Service类,Service再通过注入的方式获取到Repository类,Repository类里面有一个方法构造构造一个User对象,返回给main方法。Repository无需连接数据库,使用伪代码即可。

【思路】配置好相关文件和相关目录后,创建user设置相关属性,创建UserRepository,并写getUser()方法,创建UserService类,使用构造方法注入的方式,并写getUser()方法调用Repository中的方法,以同样的方式创建UserController。

代码链接:Spring exercises1 · 风夏/JavaEE进阶 - 码云 - 开源中国 (gitee.com)

4.总结

1. 将对象储存到Spring中:

  • 使用类注解:@Controller、@Service、@Repository、@Configuration、@Component
  • 方法注解:@Bean【注意要配合类注解一起使用】

2. Bean的命名规则:如果 ①字符长度大于1 ②首字母大写 ③第二个字母大写,则使用原类名作为Bean名称;其他情况首字母小写获取名称。

3. 从Spring中获取对象

  • 属性注入
  • 构造方法注入
  • Setter注入

4. 注入的关键字

  • @Autowired
  • @Resource【不使用与Setter注入】

5. 解决同一类型多个Bean的报错:

  • 使用@Resource(name="")
  • 使用@Qualifier("")

你可能感兴趣的:(spring,java,后端)