Bean的探究1
提到Spring总会有老哥们Bean,Context,Core三套打过来
但是Spring用过不少了,感觉好像没有用到过上面三个核心?
那么今天就从零开始探究
没有Bean行不行?没有Context行不行?
什么是Bean
我觉得一般这种时候举例是最好的,举一个Bean的例子不就啥都懂了吗
写一个Bean
定义一个 HelloWorld 类
package com.tutorialspoint;
public class HelloWorld {
private String message;
public void setMessage(String message){
this.message = message;
}
public void getMessage(){
System.out.println("Your Message : " + message);
}
}
配置bean的文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="helloWorld" class="com.tutorialspoint.HelloWorld">
<property name="message" value="Hello World!"/>
</bean>
</beans>
写Main函数
package com.tutorialspoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
}
}
为什么要用Bean
可以看到最简单的原因就是
构造函数和代码解耦
深究一下
ApplicationContext干了什么
ApplicationContext就是常说的Spring容器???
创建BeanFactory
创建Bean
getBean干了什么
获取一个Bean的实例
根据doGetBean方法,简单来说
- 从缓存中获取Bean
- 如果缓存中没有,循环获取父Bean,递归生成Bean
- 根据score看是单例还是原型
- 返回Bean
要是我不用Bean来管理new出来的对象呢?
在doGetBean中可以看到,他可以自动的递归创建对象,不用手动new
手动new就需要复杂的构造函数 和 多个new
怎么让Spring知道这是一个Bean?
三种方法:XML,注解,Java类
XML
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="helloWorld" class="com.tutorialspoint.HelloWorld">
<property name="message" value="Hello World!"/>
</bean>
</beans>
注解
用注解配置 等价上面的XML
| 注解 | 解释 |
|---|---|
| @Controller | 组合注解(组合了@Component注解),应用在MVC层(控制层),DispatcherServlet会自动扫描注解了此注解的类,然后将web请求映射到注解了@RequestMapping的方法上。 |
| @Service | 组合注解(组合了@Component注解),应用在service层(业务逻辑层) |
| @Reponsitory | 组合注解(组合了@Component注解),应用在dao层(数据访问层) |
| @Component | 表示一个带注释的类是一个“组件”,成为Spring管理的Bean。当使用基于注解的配置和类路径扫描时,这些类被视为自动检测的候选对象。同时@Component还是一个元注解。 |
Java类
用代码配置Bean
| 注解 | 解释 |
|---|---|
| @Configuration | 配置类 |
| @Bean | 该方法名默认就是Bean的名称,该方法返回值就是Bean的对象 |
@Configuration
public class ApplicationContextConfig {
@Bean
public String message() {
return "hello";
}
}
为什么要Spring容器管理Bean?
什么是Spring容器
一个Spring容器就是某个实现了ApplicationContext接口的类的实例
Spring容器就是一个Bean工厂
Bean的实例化,获取,销毁等都是由这个bean工厂
我们必须明确,Spring的核心是容器,而容器并不唯一,框架本身就提供了很多个容器的实现,大概分为两种类型:一种是不常用的BeanFactory,这是最简单的容器,只能提供基本的DI功能;还有一种就是继承了BeanFactory后派生而来的应用上下文,其抽象接口也就是我们上面提到的的ApplicationContext,它能提供更多企业级的服务,例如解析配置文本信息等等,这也是应用上下文实例对象最常见的应用场景。
为什么总喜欢问Bean的作用域
Bean的作用域
- singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
- prototype : 每次请求都会创建一个新的 bean 实例。
- request : 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
- session : 每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效。
- global-session:全局session作用域,仅仅在基于portlet的web应用中才有意义,Spring5已经没有了。Portlet是能够生成语义代码(例如:HTML)片段的小型Java Web插件。它们基于portlet容器,可以像servlet一样处理HTTP请求。但是,与 servlet 不同,每个 portlet 都有不同的会话
那么为什么?
首先,默认单例,因为
- 像Service,Controller这样的Bean,确实只需要一个就够了,调用其中的方法,不会有线程问题
- 如果每次都New一个,内存开销很大
选择不同的作用域,对应不同的场景
- singleton:没有状态的Bean,需要在服务器中永久存活
- prototype:满状态的Bean,生命很短,朝生暮死
- request:需要一个请求一个状态,存活时间不需要太长
- session:一个会话才一个状态,存活时间和session时间保持一致
恍然大悟
回到开头的问题,没有Bean行吗?
行,那么Spring这个框架到底牛在哪里,是不是必须要用他?
是不是可以将Spring理解为:
- 一个最基本的Web服务器
- IOC用来管理Bean
- AOP用来面向切面编程
- 数据库获取事务等
- 测试功能
- 各种其他的便于整合的工具集合(Springboot)