spring 原型bean,spring bean为什么是单例

  spring 原型bean,spring bean为什么是单例

  00-1010Spring singleton Bean是指原型Bean引起的问题及其解决方案。为了更直观的发现问题,我们来演示下面的代码来分析一下spring Bean的几个相关问题:1。春豆2的范围。什么是春心豆3。什么是有状态,4。Spring框架中的singleton Bean是线程安全的吗?5.5的自动装配。春豆?6.各种自动装配模式的区别?7.可以将null或空字符串注入Spring吗?8.Spring framework中有哪些不同类型的事件(都继承自ApplicationContextEvent)?9.Spring框架都用了什么?型号10。10有什么区别。FileSystemResource和ClassPathResource?11.使用Spring框架有什么好处?12.Spring 5的新特性

  

目录

 

  00-1010在Spring中,所有的beans都有一个作用域,用注释@Scope表示。容器默认使用singleton,即“singleton”顾名思义就是容器每次只为我们创建一次beans,以后还会取同一个。

  虽然我们在开发中通常会使用singletons,但是有时候还是会忍不住使用另一种类型,也就是原型模式。这时,一个问题就产生了。3360当我们在原型Bean中注入一个singleton Bean,调用原型Bean的一个方法时,我们希望singleton Bean只初始化一次,每次调用原型Bean都要重新生成。但是,结果真的和我们想的不一样。单例和原型都只初始化一次。

  00-1010首先,创建新的SpringConfig配置类:

  @ configuration @ components can( com.whb )公共类appconfig {}这只是一个配置类,指定了容器扫描“com . whb”下的类。

  然后我们在com.whb下创建两个新类:

  @ Component( Dao )@ Scope( prototype )public class index Dao { } @ Component public class index service { @ Autowired index Dao index Dao;public void test(){ system . out . println( service : this . hashcode());system . out . println( Dao : index Dao . hashcode());}}IndexDao指定了原型模式,而IndexService是默认的singleton模式。我们将IndexDao注入到IndexSerevice中,并在测试方法中打印出两个类的哈希值来验证一致性。

  创建要测试的新测试

  public class Test { public static void main(String[]args){ AnnotationConfigApplicationContext an=new AnnotationConfigApplicationContext(appconfig . class);IndexService IndexService=an . get bean(IndexService . class);indexservice . test();IndexService index service 1=an . get bean(index service . class);index service 1 . test();IndexService index service 2=an . get bean(index service . class);index service 2 . test();}}这里我们直接从容器中取IndexService次,同时调用test()方法3次。结果如下:

  问题来了。IndexService的哈希值在单个实例中不变是可以理解的,那么原型集不变的IndexDao为什么不变呢?

  

spring单例Bean引用原型Bean产生的问题及解决

其实仔细想想,这个问题很好理解。当我们第一次从容器中获取IndexService时,他会为我们创建一个实例。在创建的过程中,发现IndexService还依赖于另一个属性,所以容器会先生成索引。

 

  Dao的实例并且注入到IndexService中,然后创建出IndexService实例并且返回。

  此时容器中有着一个IndexService和一个IndexDao。当我们第二次去拿IndexService时,容器发现已经有了一个实例,并且IndexService是单例的所有它直接就返回了那个存在着的IndexService实例。虽然IndexDao设置了原型,但由于IndexService只有一次机会设置属性所以从到尾容器并没有生成第二个IndexDao实例。这也就解释了为什么哈希值每次都是一样的。

  真实情况下我们肯定不希望是这个结果,不然的话我们设置原型还有个毛线作用。

  其实spring官方文档给出了2中解决方案,点击我查看文档说明

  下面我直接贴出代码演示一遍:

  方法一:实现ApplicationContextAware

  我们来修改下IndexService的内容:

  

public class IndexService implements ApplicationContextAware{ private ApplicationContext applicationContext; public void print() { System.out.println("service:"+this.hashCode()); System.out.println("dao:"+applicationContext.getBean("dao").hashCode()); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; }}

我们通过实现ApplicationContextAware这个接口并重写setApplicationContext()这个方法可以拿到ApplicationContext对象,从而用这个对象获取容器中的Bean.

 

  结果如下:

  

 

  可以看到service还是每次都一样,符合单例设置,但是dao确每次都改变了,说明原型设置也生效了。

  上面虽然解决了这个问题,但是这种方法还是有一定的弊端:

  ApplicationContextAware是spring提供给我们的接口,IndexService是我们业务的类,我们直接实现可以说是增大了和spring框架的耦合程度。因此spring还提供了第二种方法:

  方法二:使用@LookUp注解

  我们继续修改IndexService的内容:

  

@Componentpublic abstract class IndexService { public void print() { System.out.println("service:"+this.hashCode()); System.out.println("dao:"+getIndexDao().hashCode()); } @Lookup("dao") public abstract IndexDao getIndexDao();}

可以看到使用这种方式代码简洁了很多,我们只需要声明一个抽象方法,并在该方法上面添加@Lookup(dao)注解,dao表示要注入的类名,spring容器就会自动帮我们注入IndexDao实例。

 

  结果如下:

  

 

  总结:在spring开发中可能会遇到各种各样的问题,但其实最好的解决办法就是查阅文档,毕竟这可是第一手资料!!

  

 

  

spring Bean的几个相关问题

 

  

1.Spring Bean 作用域

Spring 容器中的 bean 可以分为 5 个范围(scope配置项)。

 

  1)singleton(单例模式) :这个模式是默认的,使用该属性定义Bean时,IOC容器仅创建一个Bean实例,IOC容器每次返回的是同一个Bean实例。

  2)prototype(原型模式) :使用该属性定义Bean时,IOC容器可以创建多个Bean实例,每次返回的都是一个新的实例。

  3)request(HTTP请求) :该属性仅对HTTP请求产生作用,每次HTTP请求都会创建一个新的Bean,在请求完成以后,bean 会失效并被垃圾回收器回收。

  4)Session(会话) :该属性仅用于HTTP Session,同一个Session共享一个Bean实例。不同Session使用不同的实例。在 session 过期后,bean 会随之失效。

  5)global-session(全局会话) :该属性仅用于HTTP Session,所有的Session共享一个Bean实例。

  

 

  

2.什么是Spring inner beans

将这一个bean声明为另一个Bean的内部bean。内部bean可以用setter注入属性和构造方法注入构造参数的方式来实现。无论何时此内部bean被使用,仅仅作为被作为一个属性被调用。

 

  

 

  

3.什么是有状态、无状态

单例:某个类系统范围内只有一个实例多例:某个类在系统范围内同时有多个实例无状态类:类中没有状态信息,一般是无成员变量或成员变量的值是不变的。有状态类:类中有状态信息,一般表现成员变量的值可变,在某一时该被调用而改变状态,之后再调用时获取其正确的状态。

 

  

4.Spring框架中的单例Bean是线程安全的么

单例模式确保某一个类只有一个实例,当多用户同时请求一个服务时,容器会给每一个请求分配一个线程,这是多个线程会并发执行该请求多对应的成员方法,如果这个单例是无状态的,那么就是线程安全的,如果这个单例是有状态的就不是线程安全的。

 

  解决有状态单例线程安全的措施: 对于有状态的单例可以实现全局共享,状态的修改最好加锁,保证线程的安全性。

  

 

  

5.Spring Bean 的自动装配

1)首先用@Component注解类

 

  

@ComponentClass public Student{

2)在启动类上添加@ComponentScan注解的类, spring才能自动装配bean

 

  

@ComponentScan Class public Application{

3)开启默认扫描,spring将扫描由@Component注解的类,并且创建个实力

 

  

 

  

6.各种自动装配模式的区别

1)no: 这是 Spring 框架的默认设置,在缺省情况下,自动配置是通过ref属性手动设定。

 

  2)byName: 可以根据 bean 名称设置依赖关系。当向一个 bean 中自动装配一个属性时,容器将根据 bean 的名称自动在在配置文件中查询一个匹配的 bean。

  3)byType: 可以根据 bean 类型设置依赖关系。当向一个 bean 中自动装配一个属性时,容器将根据 bean 的类型自动在在配置文件中查询一个匹配的 bean。

  4)constructor: 在构造函数参数的byType方式。**5)、autodetect:**如果找到默认的构造函数,使用自动装配用构造; 否则,使用按类型自动装配(在Spring3.0以后的版本此模式已被废弃,已经不再合法了)。

  

 

  

7.在Spring中可以注入null或空字符串吗

没问题

 

  

 

  

8.Spring框架中有哪些不同类型的事件(都继承自ApplicationContextEvent)

1)上下文更新事件(ContextRefreshedEvent): 当ApplicationContext初始化或刷新完成后触发的事件。

 

  2)上下文开始事件(ContextStartedEvent): 当ApplicationContext启动后触发的事件

  3)上下文停止事件(ContextStoppedEvent): 当ApplicationContext停止后触发的事件。

  4)上下文关闭事件(ContextClosedEvent): 当ApplicationContext被关闭时触发该事件。当容器被关闭时,其管理的所有单例Bean都被销毁。

  5)请求处理事件(RequestHandledEvent): 在Web应用中,当一个http请求(request)结束触发该事件。

  

 

  

9.Spring框架中都用到了哪些设计模型

1)代理模式: AOP就是基于动态代理的,把公共的代码抽象出来,封装到一个模块中用于代理,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

 

  2)单例模式: 在spring配置文件中定义的bean默认为单例模式。

  使用单例模式的好处:

  (1)对于频繁使用的对象,可以省略创建对象所花费的时间,减少系统的开销;

  (2)减少new操作的次数,系统内存使用率就会降低,这将减轻GC压力,缩短GC停顿时间。

  3)模板方法: 它定义了一系列操作的模型,子类继承之后可以在模型 不变的情况下去实现自定义的操作。它可以用来解决代码重复的问题。 Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。

  4)适配器模式: 将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作。Spring AOP 的实现是基于代理模式,但是 Spring AOP 的增强或通知(Advice)使用到了适配器模式,与之相关的接口是AdvisorAdapter。Advice 常用的类型有:BeforeAdvice(目标方法调用前,前置通知)、AfterAdvice(目标方法调用后,后置通知)、AfterReturningAdvice(目标方法执行结束后,return之前)。

  5)装饰器模式: 装饰者模式可以动态地给对象添加一些额外的属性或行为。当我们需要修改原有的功能,但我们又不愿直接去修改原有的代码时,设计一个Decorator套在原有代码外面。对于InputStream,ileInputStream 、BufferedInputStream都是对InputStream功能的扩展。

  6)观察者模式: 它表示的是一种对象与对象之间具有依赖关系,当一个对象发生改变的时候,这个对象所依赖的对象也会做出反应。Spring 事件驱动模型就是观察者模式很经典的一个应用。

  7)工厂模式: BeanFactory用来创建对象的实例。

  8)委派模式: Spring 提供了 DispatcherServlet 来对请求进行分发。

  

 

  

10.FileSystemResource、 ClassPathResource 有何区别

ClassPathResource 在环境变量中读取配置文件,FileSystemResource 在配置文件中读取配置文件。

 

  

 

  

11.使用Spring框架的好处是什么

1)轻量: Spring 是轻量的。

 

  2)控制反转: 在Spring中对象有 IOC容器创建,并且通过配置注入到配置变量中。Spring通过控制反转实现了低耦合。

  3)面向切面的编程(AOP): Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。

  4)容器(IOC): IOC可以创建、管理应用中对象、对象生命周期和对象之间的关系。**5)MVC框架:**提供MVC框架,将控制逻辑代码、数据存储、试图展示分层。

  6)事务管理: Spring 提供一个持续的事务管理接口,封装事物操作代码。

  7)异常处理: Spring可以全局捕捉异常。

  

 

  

12.Spring5 新特性

1) 支持JDK 8+和Java EE7+以上版本

 

  2) 运行时兼容JDK9

  3) 运行时兼容Java EE8 API

  4) 反应式编程模型

  5) 使用注解进行编程

  6) 函数式编程

  

 

  7) 提供专门的 HTTP/2 特性支持

  8) 使用 Spring WebFlux 执行集成测试

  9) 使用 JUnit 5 执行条件和并发测试

  10) 支持Kotlin

  以上为个人经验,希望能给大家一个参考,也希望大家多多支持盛行IT。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • spring编程式事务处理,spring编程事务
  • spring编程式事务处理,spring编程事务,详解Spring学习之编程式事务管理
  • spring的核心功能模块有几个,列举一些重要的spring模块
  • spring的核心功能模块有几个,列举一些重要的spring模块,七个Spring核心模块详解
  • spring注解和springmvc的注解,SpringMVC常用注解
  • spring注解和springmvc的注解,SpringMVC常用注解,详解springmvc常用5种注解
  • spring实现ioc的四种方法,spring的ioc的三种实现方式
  • spring实现ioc的四种方法,spring的ioc的三种实现方式,简单实现Spring的IOC原理详解
  • spring事务失效问题分析及解决方案怎么做,spring 事务失效情况
  • spring事务失效问题分析及解决方案怎么做,spring 事务失效情况,Spring事务失效问题分析及解决方案
  • spring5.0新特性,spring4新特性
  • spring5.0新特性,spring4新特性,spring5新特性全面介绍
  • spring ioc以及aop原理,springmvc aop原理
  • spring ioc以及aop原理,springmvc aop原理,深入浅析Spring 的aop实现原理
  • Spring cloud网关,spring cloud zuul作用
  • 留言与评论(共有 条评论)
       
    验证码: