JAVA Spring进阶

Spring

spring简介

spring是一个轻量级的(核心jar包小),非侵入式的一站式(指同时拥有数据持久层,web层,服务层)为了简化企业级开发的框架,

spring的核心是IOC,AOP

IOC: IOC 容器是具有依赖注入功能的容器,负责对象的实例化、对象的初始化,对 象和对象之间依赖关系配置、对象的销毁、对外提供对象的查找等操作,对象 的整个生命周期都是由容器来控制。我们需要使用的对象都由 ioc 容器进行管 理,不需要我们再去手动通过 new 的方式去创建对象,由 ioc 容器直接帮我 们组装好,当我们需要使用的时候直接从 ioc 容器中直接获取就可以了。

AOP: 面向切面编程(是对面向对象编程的补充,不是spring特有), 通过一个代理对象(代理模式),在不修改原来代码的情况下,对目标类进行功能的增强,使得类与类之间的耦合度降低了. 简化了开发步骤.

BeanFactory 和 ApplicationContext

BeanFactory 和 ApplicationContext都是接口

BeanFactory 接口是spring框架的顶层的接口,用来定义如何获取bean,判断等功能.

DefaultListableBeanFactory实现BeanFactory 接口,是主要的创建bean的工厂类.

ApplicationContext 接口间接的继承BeanFactory 接口,并且扩展一些新的功能.

区别

BeanFactory 面向spring框架,比较底层

ApplicationContext 由于又实现许多的接口,增加了额外的功能

实现了BeanFactory接口的工厂,是懒加载,获取bean时才会创建对象.

实现了ApplicationContext 接口的工厂,是在启动时加载所有的类,创建对象.

SpringBean的生命周期

什么是bean

Spring Framework 的官方文档翻译一下:

在Spring中,构成应用程序骨干并由Spring IoC容器管理的对象称为bean。bean是由Spring IoC容器实例化、组装和管理的对象。

bean 是由 Spring IoC 容器实例化、组装和管理的对象。

生命周期:

对于普通的 Java 对象,当创建对象后该对象就能够使用了。一旦该对象不再被使用,则由 Java 自动进行垃圾回收。而 Spring 中的对象是 bean,bean 和普通的 Java 对象没啥大的区别,只不过 Spring 不再自己去 new 对象了,而是由 IOC 容器去帮助我们实例化对象并且管理它,我们需要哪个对象,去问 IOC 容器要即可。IOC 其实就是解决对象之间的耦合问题,Spring Bean 的生命周期完全由容器控制。

Bean 的生命周期

这里我们说的 Spring Bean 的生命周期主要指的是 singleton bean(单例bean),对于 prototype 的 bean(原型bean) ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。

我们也来复习下 Spring 中的 bean 的作用域有哪些?

singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
prototype : 每次请求都会创建一个新的 bean 实例。
request : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 request 内有效。
session : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 session 内有效。

而对于 Spring Bean 的生命周期来说有以下四个过程:

  • 实例化 Instantiation
  • 属性赋值 Populate
  • 初始化 Initialization
  • 销毁 Destruction(是在容器关闭时调用的)

细化

1.instantiate bean 对象实例化

2.populate properties 属性赋值

3.1 如果 Bean 实现 BeanNameAware 执行 setBeanName

3.2 如果 Bean 实现 BeanFactoryAware 或者 ApplicationContextAware 设 置工厂 setBeanFactory 或者上下文对象 setApplicationContext 对象. 初始化 .........

3.3 如果存在类实现 BeanPostProcessor(AOP) ,执行 postProcessBeforeInitialization

3.4 如果 Bean 实现 InitializingBean 执行 afterPropertiesSet 如果配置了自己的初始化方法<bean init-method="init"> 则执行自己写的初始化方法

3.5 如果存在类实现 BeanPostProcessor(AOP) ,执行 postProcessAfterInitialization

4.完整的 bean 创建好,将 bean 对象放入到容器中,可以使用

5.销毁 如果 Bean 实现 DisposableBean 执行 destroy 如果配置了自己的销毁方法<bean destroy-method="customerDestroy"> 指定销毁方法 customerDestroy

Spring 中的bean 是线程安全的吗?

结论: 不是线程安全的

Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体scope(作用域)单例与原型Bean分别进行说明。

原型Bean
对于原型Bean,每次请求都会创建一个新对象,也就是线程之间并不存在Bean共享,自然是不会有线程安全的问题。

单例Bean
对于单例Bean,所有线程都共享一个单例实例Bean,因此是存在资源的竞争。

如果单例Bean,是一个无状态Bean(有状态,可以用来存储数据的;无状态的: 没有存储数据 Service,Dao 层只是方法调用 ),也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Spring mvc 的 Controller、Service、Dao等,这些Bean大多是无状态的。

springBean循环依赖问题

JAVA 中循环依赖场景
很简单,就是 A 对象依赖了 B 对象,B 对象依赖了 A 对象。不考虑spring循环依赖是正常的。

 但是循环依赖在spring中 就会出现问题, spring中并不是简单的new出对象,而是经过bean的生命周期。在bean的依赖注入阶段A需要注入B,由于B还没有被创建,要先去创建B,但是B中又需要注入A,A又因为无法注入B而无法完成创建(有点类似死锁)就卡在了这里,无法进行。

产生循环依赖的问题,主要是:A 创建时-->需要 B----B 去创建--->需要 A,从而产生了循环。

 spring解决循环依赖问题

spring运用三级缓存解决该问题

在 DefaultSingletonBeanRegistry 类中定义了 3 个 Map 对象充当缓存.
singletonObjects: 一级缓存,用于保存实例化、注入、初始化完成的 bean.实例
earlySingletonObjects: 二级缓存,用于保存实例化完成的 bean 实例,提前曝露对象.
singletonFactories: 三级缓存,用于保存创建 bean 的工厂对象

当A中需要B时, 那么先从A会从一级缓存中去找B,如果没有,然后到二级缓存中找B,也没有,就去三级缓存中,找到B对应的工厂,创建出B对象(原始对象,半成品)把B对象放到了二级缓存中,将三级缓存中的工厂对象删除。然后完成A的创建后再去依赖注入完成B的创建。创建完成后会将A,B放入一级缓存。

Servlet 的过滤器与 Spring 拦截器区别

 过滤器 Filter 是在请求进入容器后,但在进入 servlet 之前进行预处理,需要服务器来进行控制。

拦截器 Interceptor 是在请求进入 servlet 后,在进入 Controller 之前进行预处理的,Controller 中渲染了对应的视图之后请求结束。

spring常见注解

声明 bean 的注解
@Component:泛指各种组件,@Controller、@Service、@Repository 都可以称为@Component
@Controller:控制层
@Service:业务层
@Repository:数据访问层
Bean 的生命周期属性
@Scope 设置类型包括:设置 Spring 容器如何新建 Bean 实例
singleton:单例,一个 Spring 容器中只有一个 bean 实例,默认模式
protetype:每次调用新建一个 bean
request:web 项目中,给每个 http request 新建一个 bean
session:web 项目中,给每个 http session 新建一个 bean
globalSession:给每一个 global http session 新建一个 Bean 实例
注入 bean 的注解
@Autowired:由 Spring 提供
@Qualifier: 当有多个同一类型的 Bean 时,可以用@Qualifier(“name”)来指定。与@Autowired 配合使用.
@Resource:由 java 提供
切面(AOP)相关注解
Spring 支持 AspectJ 的注解式切面编程
@Aspect:声明一个切面
@After:在方法执行之后执行(方法上)
@Before:在方法执行之前执行(方法上)
@Around:在方法执行之前与之后执行(方法上)
@PointCut:声明切点
@EnableAspectJAutoProxy:开启 Spring 对 AspectJ 代理的支持
SpringMVC 常用注解
@RestController : 该 注 解 为 一 个 组 合 注 解 , 相 当 于 @Controller 和 @ResponseBody 的组合,注解在类上,意味着,该 Controller 的所有方法都默认加@ResponseBody。
@RequestMapping:用于映射 web 请求,包括访问路径和参数
@ResponseBody:支持将返回值放到 response 内,而不是一个页面,通常用户返回 json 数据
@RequestBody:允许 request 的参数在 request 体中,而不是在直接连接的地址后面
其他注解
@JsonFormat 此注解用于属性或者方法上(最好是属性上),可以方便的把 Date 类型直接转化为我们想要的模式.
@Transactional 注解放在类级别时,表示所有该类的公共方法都配置相同的事务属性信息。
SpringBoot 注解
@SpringBootApplication:
包含@Configuration、@EnableAutoConfiguration、@ComponentScan 通常用在主类上@RestControllerAdvice,@ExceptionHandler 用于统一异常处理,捕获指定的异常.
配置类相关注解
@Configuration:声明当前类为配置类
@Bean:注解在方法上,声明当前方法的返回值为一个 bean,替代 xml 中的方式
@ComponentScan:用于对 Component 类型注解进行扫描

 springBoot自动装配

在springboot程序启动时,spring是如何知道应该加载哪些组件,不应该加载哪些组件?

自动装配基本流程概述
springBoot 启动时,首先对 application.yml 和 pom.xml 文件进行读取,获取 到项目中使用到的第三方组件,然后读取 spring.factories 中的 spring 支持的配置类,最后加载项目中所使用到的组件配置类.
启动类
@SpringBootApplication 注解是一个复合注解
@ComponentScan 扫描启动类所在包下所有添加注解的类

 在@EnableAutoConfiguration 中有一个 @Import({AutoConfigurationImportSelector.class})注解,其中包含 AutoConfigurationImportSelector 类. AutoConfigurationImportSelector导入并选择需要加载组件,读取 meta-info/spring.factories 文件中所有组件的自动配置类,只需加载我们在pom.xml中配置的组件配置类,把meta-info/spring.factories多余的组件剔除

AutoConfigurationImportSelector 类中关键方法, 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值