博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
初识Spring Framework——Bean、注册Bean、依赖注入
阅读量:4136 次
发布时间:2019-05-25

本文共 5869 字,大约阅读时间需要 19 分钟。

目录

简述Spring容器

传统方式: new对象,然后调用对象的属性或方法 User user = new User();

spring方式:把对象存入spring容器种,用的时候从容器中取出,随后调用对象的属性或方法

在这里插入图片描述

注册Bean的三种方式

方式一:类注解

a)Controller —— 前端业务交互层【参数效验】

b)Service —— 业务处理的中间层【业务处理】
c)Reoisitory —— 数据持久层
d)Component —— 通用对象工具类

import org.springframework.stereotype.Controller;@Controllerpublic class LoginController {
}

定义好了Bean对象,注册到容器中以后,就可以获取Bean对象了,在入口类 org.example.App 中,可以通过 ApplicationContext 对象获取Bean,有两种方式获取:

  • 通过类型获取:这种获取方式要求该类型的Bean只能有一个
  • 通过名称获取:同一个类型的Bean可以有多个
  • 类名+名称:获取到唯一的Bean
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); LoginController loginController = (LoginController) context.getBean("loginController"); System.out.println(loginController); //关闭容器 ((ClassPathXmlApplicationContext)context).close(); }

方式二:@Bean

也可以当作方法注解。当前类被 Spring 扫描到时,可以在方法上使用 @Bean 注解,通过方法返回类型,也可以定义、注册Bean对象,默认使用方法名作为Bean的名称。

创建一个实体类

package org.example.model;import lombok.Getter;import lombok.Setter;import lombok.ToString;@Setter@Getter@ToStringpublic class User {
private String name; private String password;}

这里用到了 lombok 插件,用注解自动生成get、set、toString方法,它用自定义注解的方式,在代码编译的时候,将自定义的注解换成 JVM 可以执行的方法。(传统的 get、set、tostring方法)

用 @Bean 的方式使方法进行依赖注入

package org.example.controller;import lombok.Getter;import org.example.model.User;import org.springframework.context.annotation.Bean;import org.springframework.stereotype.Controller;@Controller@Getterpublic class LoginController {
@Bean public User user1() {
User user = new User(); user.setName("悟空"); user.setPassword("妖怪哪里跑"); return user; } @Bean public User user2() {
User user = new User(); user.setName("八戒"); user.setPassword("背媳妇回家"); return user; }}

在 App 中调用容器中的 User 对象

package org.example;import org.example.controller.LoginController;import org.example.model.User;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import java.beans.Introspector;public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); User user = (User)context.getBean("user1"); System.out.println(user); User user2 = context.getBean("user2",User.class); System.out.println(user2); //关闭容器 ((ClassPathXmlApplicationContext)context).close(); }}

方式三:@Configuration

在类被Spring扫描到时,使用 @Configuration 注解,可以注册一个配置类到容器中。

package org.example.config;import org.springframework.context.annotation.Configuration;@Configurationpublic class MyApplication {
}

对象注入的三种方式(从spring获取对象)

方式一:@Autowired 属性注入

在服务层添加 LoginService 对象,并提供 sayHi 方法

import org.springframework.stereotype.Service;//存储@Servicepublic class LoginService {
public void sayHi() {
System.out.println("Login-sayhi!"); }}

在控制层添加 LoginService 对象,然后调用该对象的 sayHi 方法

@Controller@Getterpublic class LoginController {
//第一种注入(查询)方式:属性注入 @Autowired private LoginService loginService; public void sayHi() {
//参数效验 loginService.sayHi(); }}

最后在主方法内调用 loginController 对象即可

public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); LoginController loginController = context.getBean(LoginController.class); loginController.sayHi(); //关闭容器 ((ClassPathXmlApplicationContext)context).close(); }}

在这里插入图片描述

正常的执行了 sayHi 方法

ps:第一种方式属性名称,注入有多个对象的类的对象时,名称不能够随便起,会导致无法识别

如果实在想起别名,那么可以添加 @qualifier 注释来起别名

private User u1;        @Autowired    @Qualifier("user1")    public void setU1(User u1) {
this.u1 = u1; }

方式二:通过 Set 的方式注入

与第一种不同的是,此时的 @Autowired 修饰的是 set 方法,通过 set 方法来注入对象

(该方式参数变量名可随意取)

@Controller@Getterpublic class LoginController {
//第二种注入的方式:通过 Set 的方式注入 private LoginService loginService; @Autowired public void setLoginService(LoginService loginService) {
this.loginService = loginService; } public void sayHi() {
//参数效验 loginService.sayHi(); }}

方式三:构造方法注入

此方法加不加 @Autowired 都可以正常执行,但建议加上

@Controller@Getterpublic class LoginController {
//第三种注入的方式:构造函数注入 private LoginService loginService; @Autowired public LoginController(LoginService loginService) {
this.loginService = loginService; } public void sayHi() {
//参数效验 loginService.sayHi(); }}

Spring 各层之间联系

在这里插入图片描述

Bean

Bean 其实就是对象,只不过在 Spring 种叫作 Bean

Bean 的作用域(Bean的类型)

单例 (singleton)

描述:该作用域下的Bean在IoC容器中只存在一个实例:获取Bean(即通过applicationContext.getBean等方法获取)及装配Bean(即通过@Autowired注入)都是同一个对象。

场景:通常无状态的Bean使用该作用域。无状态表示Bean对象的属性状态不需要更新

备注:Spring默认选择该作用域

创建新对象 (prototype)

描述:每次对该作用域下的Bean的请求都会创建新的实例:获取Bean(即通过applicationContext.getBean等方法获取)及装配Bean(即通过@Autowired注入)都是新的对象实例。

场景:通常有状态的Bean使用该作用域

request

描述:每次http请求会创建新的Bean实例,类似于prototype

场景:一次http的请求和响应的共享Bean

备注:限定SpringMVC中使用

session

描述:在一个http session中,定义一个Bean实例

场景:用户回话的共享Bean, 比如:记录一个用户的登陆信息

备注:限定SpringMVC中使用

application

描述:在一个http servlet Context中,定义一个Bean实例

场景:Web应用的上下文信息,比如:记录一个应用的共享信息

备注:限定SpringMVC中使用

websocket

描述:在一个HTTP WebSocket的生命周期中,定义一个Bean实例

场景:WebSocket的每次会话中,保存了一个Map结构的头信息,将用来包裹客户端消息头。第一次初始化后,直到WebSocket结束都是同一个Bean。

备注:限定Spring WebSocket中使用

Bean 的生命周期

在这里插入图片描述

总结 Bean 生命周期

主要步骤为:

  1. 实例化Bean:通过反射调用构造方法实例化对象。
  2. 依赖注入:装配Bean的属性
  3. 实现了Aware接口的Bean,执行接口方法:如顺序执行BeanNameAware、BeanFactoryAware、ApplicationContextAware的接口方法。
  4. Bean对象初始化前,循环调用实现了BeanPostProcessor接口的预初始化方法(postProcessBeforeInitialization)
  5. Bean对象初始化:顺序执行@PostConstruct注解方法、InitializingBean接口方法、init-method方法
  6. Bean对象初始化后,循环调用实现了BeanPostProcessor接口的后初始化方法(postProcessAfterInitialization)
  7. 容器关闭时,执行Bean对象的销毁方法,顺序是:@PreDestroy注解方法、DisposableBean接口方法、destroy-method

ps:第一步的实例化是指new对象,Spring的语义中说初始化Bean包含Bean生命周期中的初始化步骤

转载地址:http://lixvi.baihongyu.com/

你可能感兴趣的文章
Linux kmalloc
查看>>
How SKBs work
查看>>
usb设备的probe全过程
查看>>
Preparing Files for TFTP Net Booting
查看>>
git format-patch origin 生成patch
查看>>
配置网络
查看>>
Linux wget 命令
查看>>
nfs server problem in Linux 2.6.32
查看>>
Linux内核中的jiffies
查看>>
Extracting U-boot/PPCboot ramdisk
查看>>
There is no ~/.bashrc to setup user $PATH
查看>>
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?
查看>>
Linux Spin lock.
查看>>
Linux, BUG: spinlock recursion on CPU
查看>>
Ubuntu 设置 DNS
查看>>
Ubuntu 设置 dhcpd 不要自动启动
查看>>
Including driver firmware on Linux kernel image
查看>>
can't boot the kernel , if the server side is tftpd32.exe
查看>>
Upstream src code to Android
查看>>
Commit our mod to our own repo server
查看>>