获取 Bean 对象(对象装配)

目录

一、添加注解存储 Bean 对象

1)类注解

2)方法注解@Bean

二、添加注解获取 Bean 对象(对象装配)

①属性注入

②构造方法注入

③Setter 注⼊


Spring是一个包含众多工具的IoC容器(容器中装的是对象)

Spring两大核心思想:IoCAOP【重要面试题!!】

IoC(Inversion of Control) 翻译成中⽂是“控制反转”的意思,即控制权反转,将创建对象的控制权,交给了Spring(优点:解耦)

Spring帮我们管理对象

①告诉Spring,帮我们管理哪些对象【存】

②知道如何取出来这些对象【取】(DI

也就是说学 Spring 最核⼼的功能,就是学如何将对象存⼊到 Spring 中,再从 Spring 中获取对象的过 程。

Spring 是⼀个 IoC 容器,说的是对象的创建和销毁的权利都交给 Spring 来管理了,它本身⼜具备了存 储对象和获取对象的能⼒。

将对象存放到容器中的好处:将对象存储在 IoC 容器相当于将以后可能⽤的所有⼯具制作好都放到仓 库中,需要的时候直接取就⾏了,⽤完再把它放回到仓库。⽽ new 对象的⽅式相当于,每次需要⼯具 了,才现做,⽤完就扔掉了也不会保存,下次再⽤的时候还得重新做,这就是 IoC 容器和普通程序开 发的区别。)

DI(Dependency Injection)依赖注入

所谓依赖注⼊,就是由 IoC 容器在运⾏期间,动态地将某种依赖关系注⼊到对象之中。所以,依 赖注⼊(DI)和控制反转(IoC)是从不同的⻆度的描述的同⼀件事情,就是指通过引⼊ IoC 容 器,利⽤依赖关系注⼊的⽅式,实现对象之间的解耦。 IoC 是“⽬标”也是⼀种思想,⽽⽬标和思想只是⼀种指导原则,最终还是要有可⾏的落地⽅案,⽽ DI 就 属于具体的实现。

⽐如说我今天⼼情⽐较好,吃⼀顿好的犒劳犒劳⾃⼰,那么“吃⼀顿好的”是思想和⽬标(是 IoC), 但最后我是吃海底捞还是杨国福?这就是具体的实现,就是 DI。

Bean

在 Java 语⾔中对象也叫做 Bean

一、添加注解存储 Bean 对象

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

类注解@Controller(控制器存储) @Service(服务存储) @Repository(仓库存储) @Component(组件存储) @Configuration(配置存储) 【五大注解】

方法注解@Bean

1)类注解
@Controller // 将对象存储到 Spring 中
public class UserController {
    public void sayHi(String name) {
        System.out.println("Hi," + name);
   }
}

此时我们先使⽤之前读取对象的⽅式来读取上⾯的 UserController 对象

public class Application {
    public static void main(String[] args) {
        // 1.得到 spring 上下⽂
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        // 2.得到 bean
        UserController userController = (UserController) 
context.getBean("userController");
        // 3.调⽤ bean ⽅法
        userController.sayHi("Bit");
   }
}

既然功能是⼀样的,为什么需要这么多的类注解呢?

原因是让程序员看到类注解之后,就能直接了解当前类 的⽤途,⽐如: @Controller:表示的是业务逻辑层; @Servie:服务层; @Repository:持久层; @Configuration:配置层。

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

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

注意 Bean 的命名

如果第一个字母和第二个字母都为大写,则不变;其他情况则将首字母小写

2)方法注解@Bean

放在方法上,并且⽅法注解 @Bean 要配合类注解才能将对象正常的存储到 Spring 容器中

@Component
public class User {
    @Bean
    public User user1() {
        User user = new User();
        user.setId(1);
        user.setName("Java");
        return user;
   }
}
public class Application {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        User user = (User) context.getBean(User.class);//通过类型获取对象,只适用于一个类型存在一个bean时
        User user = (User) context.getBean("user1");//通过方法名来获取
        User user = (User) context.getBean("user1",User.class);//通过方法名和类名来获取
        System.out.println(user.toString());
   }
}

@Bean传递参数

重命名 Bean

使用@Bean注解时,benan的名称默认是方法名

可以通过设置 name 属性给 Bean 对象进⾏重命名操作

@Component
public class Users {
    @Bean(name = {"u1"})
    public User user1() {
        User user = new User();
        user.setId(1);
        user.setName("Java");
        return user;
   }
}
class App {
    public static void main(String[] args) {
        // 1.得到 spring 上下⽂
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        // 2.得到某个 bean
        User user = (User) context.getBean("u1");
        // 3.调⽤ bean ⽅法
        System.out.println(user);
   }
}

这个重命名的 name 其实是⼀个数组,⼀个 bean 可以有多个名字,并且 name={} 可以省略

@Bean({"u1", "us1"})
public User user1() {
    User user = new User();
    user.setId(1);
    user.setName("Java");
    return user;
}

二、添加注解获取 Bean 对象(对象装配)

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

对象装配(对象注⼊)的实现⽅法以下 3 种:

1. 属性注⼊ 2. 构造⽅法注⼊ 3. Setter 注⼊

下⾯我们按照实际开发中的模式,将 Service 类注⼊到 Controller 类中。

①属性注入

使⽤ @Autowired 实现

属性注入以类型进行匹配,与注入的属性名称无关,但一个类型存在多个对象时,优先名称·匹配,如果名称匹配不上,那就报错)

@Service
public class UserService {
    public User getUser(Integer id){
        User user=new User();
        user.setId(id);
        user.setName("Java-"+id);
        return user;
    }
}
@Controller
public class UserController {
    //属性注入
    @Autowired
    private  UserService userService;
    public User getUser(Integer id){
        return  userService.getUser(id);
    }
}
public class App {
    public static void main(String[] args) {
        //1.得到Spring上下文对象
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
       
        //2.加载某个bean
        UserController userController=context.getBean(UserController.class);
        //3.调用相应方法
        System.out.println(userController.getUser(1).toString());
    }
}

②构造方法注入

在类的构造⽅法中实现注⼊

@Controller
public class UserController2 {
    // 注⼊⽅法2:构造⽅法注⼊
    private UserService userService;
 @Autowired
    public UserController2(UserService userService) {
        this.userService = userService;
   }
    public User getUser(Integer id) {
        return userService.getUser(id);
   }
}

③Setter 注⼊
@Controller
public class UserController3 {
    // 注⼊⽅法3:Setter注⼊
    private UserService userService;
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
   }
    public User getUser(Integer id) {
        return userService.getUser(id);
   }
}

三种注⼊优缺点分析【常见面试题】

属性注⼊

 优点:简洁,使⽤⽅便;

缺点: ①只能⽤于IoC容器,如果是⾮IoC容器不可⽤,并且只有在使⽤的时候才会出现NPE(空指 针异常) ②不能注⼊⼀个Final修饰的属性

构造函数注⼊

优点:①可以注⼊final修饰的属性 ②注⼊的对象不会被修改

依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法 是在类加载阶段就会执⾏的⽅法. ③通⽤性好,构造⽅法是JDK⽀持的,所以更换任何框架,他都是适⽤的

缺点: 注⼊多个对象时,代码会⽐较繁琐

Setter注⼊

优点:⽅便在类实例之后,重新对该对象进⾏配置或者注⼊

缺点:①不能注⼊⼀个Final修饰的属性 ②注⼊对象可能会被改变,因为setter⽅法可能会被多次调⽤,就有被修改的⻛险.

关于@Autowired注解的省略

①在属性上进行注入时,必须使用@Autowired注解。

②如果一个类只有一个构造函数,并且这个构造函数是默认的(没有参数),可以省略③@Autowired注解,Spring Boot会自动识别这个构造函数进行注入

如果类中有一个或多个Setter方法,并且这些方法只有一个参数,那么也可以省略@Autowired注解

除了可以使⽤ @Autowired 关键字之外,我们还可以使⽤ @Resource 进⾏注⼊

@Controller
public class UserController {
    // 注⼊
    @Resource
    private UserService userService;
    public User getUser(Integer id) {
        return userService.getUser(id);
   }
}

@Autowired 和 @Resource 的区别

出身不同:@Autowired 来⾃于 Spring,⽽ @Resource 来⾃于 JDK 的注解;

使⽤时设置的参数不同:相⽐于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如 name 设置,根据名称获取 Bean。

当出现以下多个 Bean,返回同⼀对象类型时程序会报错

@Component
public class Users {
    @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 {
    // 注⼊
    @Resource
    private User user;
    public User getUser() {
        return user;
   }
}

如何解决??

①使⽤ @Resource(name="user1") 定义

@Controller
class UserController4 {
    // 注⼊
    @Resource(name = "user1")
    private User user;
    public User getUser() {
        return user;
   }
}

②使⽤ @Qualifier 注解定义名称。

在@Qualifier的value属性中,指定注⼊的bean 的名称,指定当前要注⼊的bean对象

@Controller
public class UserController5 {
    // 注⼊
    @Autowired
    @Qualifier(value = "user2")
    private User user;
    public User getUser() {
        return user;
   }
}

@Qualifier注解不能单独使⽤,必须配合@Autowired使⽤

③@Primary确定默认实现

@Component
public class BeanConfig {
 @Primary //指定该bean为默认bean的实现 
 @Bean("u1")
 public User user1(){
 User user = new User();
 user.setName("zhangsan");
 user.setAge(18);
 return user;
 }
 @Bean
 public User user2() {
 User user = new User();
 user.setName("lisi");
 user.setAge(19);
 return user;
 }
}

常⻅⾯试题:@Autowird与@Resource的区别

• @Autowired是spring框架提供的注解,⽽@Resource是JDK提供的注解

• @Autowired默认是按照类型注⼊,⽽@Resource是按照名称注⼊.相⽐于@Autowired来说, @Resource⽀持更多的参数设置,例如name设置,根据名称获取Bean。

面试题

常⻅注解有哪些?分别是什么作⽤?  

weburl映射:@RequestMapping

参数接收和接⼝响应:@RequestParam,@RequestBody,@ResponseBody bean的存储:@Controller,@Service,@Repository,@Component,@Configuration, @Bean

bean的获取:@Autowired,@Qualifier,@Resource

  • 15
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值