目录

存储Bean

配置文件中设置扫描路径

使用注解存储Bean

五大类注解存储Bean

五大类注解之间的关系

为什么要有五大类注解

@Bean方法注解存储方法返回值

注入Bean

属性注入

Setter方法注入

构造方法注入

@Resource注解

存储Bean

上篇文章的存储Bean是在Spring的配置文件下通过bean标签来把Bean存储到Spring容器中,其中需要设置标签属性id 和 name,还是比较麻烦的,接下来介绍一种更为简单也最为常用的方法来存储Bean。

配置文件中设置扫描路径

首先还是要在配置文佳中设置一下。这里需要设置的是要存储的Bean对象的路径。

比如我想把test包下面的这几个类存储到Spring中,此时就需要在配置文件中写一下扫描的路径。

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

有关扫描路径需要注意的点:

1. 只有在扫描路径下的类,加了注解的才能被存储到Spring中

2. 扫描路径是可以提升效率的,不至于在整个项目中找要存储的类 

使用注解存储Bean

上述工作完成后就可以通过注解存储Bean。注解分为两大类,一类是类注解,一类是方法注解。

五大类注解存储Bean

这五个注解分别是  @Controller  @Component  @Configuration  @Repository  @Service

使用演示:

package com.test;

import org.springframework.stereotype.Controller;

@Controller

public class UserController {

public void doController() {

System.out.println("doUserController");

}

}

import com.test.UserController;

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");

// 测试Controller

UserController userController = context.getBean("userController", UserController.class);

userController.doController();

}

}

上面获取到Bean时,第一个参数直接就是把类的第一个字母小写了(大驼峰变成小驼峰)

这只是其中的一个对Bean名字的处理方式,接下来来看另外一种。

package com.test;

import org.springframework.stereotype.Controller;

// 当类的第一、二的字母都是大写的情况

@Controller

public class UController {

public void doController() {

System.out.println("doUController");

}

}

 

 

为什么会有两个处理情况,通过查看源码可知。

其他四个注解也都是相同的命名规则,也是相同的用法,就不一一演示了。

小结:

1. 使用注解来存储的前提是配置文件中已经设置好了路径

2. 只有在配置文件路径下加了注解才能把Bean存储到Spring中,二者同时成立才可以

3. 取出Spring的bean时,有两种方法:

    a. 如果类名的前两个字母并非都为大写字母,则在取的时候变成首字母小写

    b. 如果前两个字母都是大写,在取的时候使用原类名即可

五大类注解之间的关系

可以看出,@Service  @Repository  @Controller @Configuration  这四个注解都是相当于 拓展了 @Component 这个注解,所以它们的使用方式基本都一致。

为什么要有五大类注解

当程序员看到五大类注解后,就会知道这个类具体是干什么的。

@Bean方法注解存储方法返回值

1. 在配置文件中把把方法所在的类的路径配置好

2. 在方法上加@Bean注解,同时在方法所在的类上面加上五大类注解

package com.test.component;

import com.test.entity.User;

import org.springframework.context.annotation.Bean;

import org.springframework.stereotype.Component;

@Component

public class UserBeans {

@Bean

public User getUserById() {

User user = new User();

user.setUserId(1);

user.setUserName("张三");

user.setUserAge(20);

return user;

}

}

import com.test.entity.User;

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注解

User user = context.getBean("getUserById", User.class);

System.out.println(user.getUserName());

}

}

如果不加类注解:

上面获取到方法返回的Bean是通过方法名,这和之前五大注解的获取Bean又是另外一套规则。但是通过方法名获取通常是不使用的,我们可以在@Bean注解后重写命名,通过新名字来获取,同时使用原方法名就获取不到Bean了。

小结: 

1. @Bean方法注解必须在五大类注解下使用(被五大类修饰的类)

2. 该注解如果没用重命名,那么直接使用方法名就可以获取到Bean

3. 如果重命名后,只能使用新的名字,方法名无法继续使用

4. 新名字可以有很多,使用数组保存

5. 该注解是把方法的返回值存入到Spring中,如果方法没有返回值,就不能使用该注解

注入Bean

把对象从Spring中取出来到某个类中使用。

属性注入

package com.test.service;

// 测试从Spring中拿user对象注入UserController类中

import com.test.entity.User;

import org.springframework.stereotype.Service;

@Service()

public class UserService {

// 实际上要连接数据库通过id查询到对象

public User getUser(Integer id) {

User user = new User();

user.setUserName("张三");

user.setUserId(123);

user.setUserAge(20);

return user;

}

}

package com.test.controller;

import com.test.entity.User;

import com.test.service.UserService;

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

import org.springframework.stereotype.Controller;

@Controller

public class UserController {

// 通过属性注入

@Autowired

private UserService userService;

public User getUserByAttribute(Integer id) {

return userService.getUser(id);

}

}

import com.test.controller.UserController;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App2 {

public static void main(String[] args) {

// 获取到Spring容器

ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

// 获取到Bean对象

UserController userController = context.getBean("userController", UserController.class);

System.out.println(userController.getUserByAttribute(123).toString());

}

}

优点:

高效便捷:使用属性注入时,无需编写额外的构造方法或Setter方法,可以大大降低代码量并提高开发效率。 可读性强,很容易从代码层面看出有哪些Bean被注入了

 缺点:

无法注入final修饰的修饰的对象。因为final修饰的对象只能被赋值一次,而在Spring容器中,属性注入是通过反射实现的,它需要通过反射来修改对象的属性值,但是final修饰的对象属性是不可变的,不能被修改,因此无法进行属性注入。对象有可能会被修改。因为注入的Bean可以使用很多次。只能在IoC容器下使用,其他的不行不能保证对象完全初始化  原因有以下两点:

            a:Bean依赖关系不完整,当某个Bean依赖的其他Bean还未完全初始化或者还未注                   入时就会出现这种情况。

            b:Bean的声明周期管理不当(下篇文章讲)

Setter方法注入

package com.test.controller;

import com.test.entity.User;

import com.test.service.UserService;

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

import org.springframework.stereotype.Controller;

@Controller

public class UserController {

private UserService userService;

// 通过Setter方法注入

@Autowired

public void setUserService(UserService userService) {

this.userService = userService;

}

public User getUserBySetter(Integer id) {

return userService.getUser(id);

}

}

import com.test.controller.UserController;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App2 {

public static void main(String[] args) {

// 获取到Spring容器

ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

// 获取到Bean对象

UserController userController = context.getBean("userController", UserController.class);

System.out.println(userController.getUserBySetter(123).toString());

}

}

优点:

灵活性高,相较于构造方法注入,它可以在任何时候注入 符合单一设计原则(每个方法只传一个对象)

缺点:

不能注入final修饰的对象。只用Java8及以下的不可以,原因同上。但是Java9及以后的可以,因为引入了Variable Handles的机制,可以通过反射来修改final字段的值。对象可能会被修改

构造方法注入

package com.test.controller;

import com.test.entity.User;

import com.test.service.UserService;

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

import org.springframework.stereotype.Controller;

@Controller

public class UserController {

private UserService userService;

// 通过构造方法注入

@Autowired

public UserController(UserService userService) {

this.userService = userService;

}

public User getUserByConstructor (Integer id) {

return userService.getUser(id);

}

}

import com.test.controller.UserController;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App2 {

public static void main(String[] args) {

// 获取到Spring容器

ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

// 获取到Bean对象

UserController userController = context.getBean("userController", UserController.class);

System.out.println(userController.getUserByConstructor(123).toString());

}

}

特点:

当只有一个构造方法的时候,@AutoWired这个注解可以省略

因为这是官方推荐使用的方法

优点:

可以注入一个被final修饰的对象。因为除了一开始就赋值,还可以在构造方法中对final修饰的属性赋值。被注入的对象不可变。因为构造方法只能在最开始执行一次。可以保证被注入的对象完全初始化通用性更好,可以在IoC之外的地方使用。

@Resource注解

这是JDK提供的注入Bean的注解,和@AutoWired有以下的区别。

@Resource是JDK提供的,@AutoWired是Spring提供的@Resource只能不能使用构造方法注入,@AutoWired都可以@Resource可以设置很多参数,而@AutoWired只能设置一个

 有什么错误评论区指出。希望可以帮到你。

精彩链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: