Java——Spring得Bean详解(一文搞懂Spring的Bean)

1、什么是Spring Beans

答: Spring Beans 是那些形成Spring应用的主干的Java对象。它们被Spring IOC容器初始化,装配和管理。这些Bean通过容器中配置的元数据创建。比如,以XML文件中的形式定义。

2、Spring如何获取Bean?

  • 在初始化时保存 ApplicationContext 对象;
ApplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml"); 
ac.getBean("beanId");
  • 通过 Spring 提供的工具类(WebApplicationContextUtils)获取**ApplicationContext**对象;
public String test(HttpServletRequest request,HttpServletRequest response) {
    WebApplicationContext wc = RequestContextUtils.findWebApplicationContext(request);
    wc.getBean("beanName");
    
    WebApplicationContext wc2 = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
    wc2.getBean("beanName");
}
  • 继承自抽象类 ApplicationObjectSupport
WebApplicationContext wac = (WebApplicationContext)servletContext
.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
  • 继承自抽象类 WebApplicationObjectSupport
  • 实现接口 ApplicationContextAware
public class SpringContextUtil implements ApplicationContextAware { 
 // Spring应用上下文环境 
 private static ApplicationContext applicationContext; 
 /** 
 * 实现ApplicationContextAware接口的回调方法,设置上下文环境 
 * 
 * @param applicationContext 
 */ 
 public void setApplicationContext(ApplicationContext applicationContext) { 
   SpringContextUtil.applicationContext = applicationContext; 
 } 
 /** 
 * @return ApplicationContext 
 */ 
 public static ApplicationContext getApplicationContext() { 
   return applicationContext; 
 } 
 /** 
 * 获取对象 
 * 
 * @param name 
 * @return Object
 * @throws BeansException 
 */ 
 public static Object getBean(String name) throws BeansException { 
   return applicationContext.getBean(name); 
 } 
}
  • 通过 Spring 提供的 ContextLoader 加载。
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
wac.getBean(beanID);

3、什么是元数据?

答: 元数据是指用来描述数据的数据,更通俗一点,就是描述代码间关系,或者代码与其他资源(例如数据库表)之间内在联系的数据。在一些技术框架,如strutsEJBhibernate就不知不觉用到了元数据。对struts来说,元数据指的是struts-config.xml;对EJB来说,就是ejb-jar.xml和厂商自定义的xml文件;对hibernate来说就是hbm文件。以上阐述的几种元数据都是基于xml文件的或者其他形式的单独配置文件。

  • 与被描述的文件分离,不利于一致性的维护;
  • 所有这样文件都是ASCII文件,没有显式的类型支持。

基于元数据的广泛应用,JDK5.0引入了Annotation的概念来描述元数据。在Java中,元数据以标签的形式存在于 Java 代码中,元数据标签的存在并不影响程序代码的编译和执行。

Annotation就像代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取。读取到了程序元素的元数据,就可以执行相应的处理。通过注解,程序开发人员可以在不改变原有逻辑的情况下,在源代码文件中嵌入一些补充信息。代码分析工具、开发工具和部署工具可以通过解析这些注解获取到这些补充信息,从而进行验证或者进行部署等。

4、一个 Spring Bean 定义包含什么?

答: 一个Spring Bean的定义包含容器必知的所有配置元数据,包括如何创建一个Bean,它的生命周期详情及它的依赖。

5、如何给Spring 容器提供配置元数据?Spring有几种配置方式?

答: 这里有三种重要的方法给Spring容器提供配置元数据。

  • XML配置文件。
  • 基于注解的配置。
  • 基于Java的配置。

6、Spring配置文件包含了哪些信息?

答: Spring配置文件是个**XML**** 文件**,这个文件包含了类信息、如何配置它们以及类之间的依赖关系。

7、Spring基于xml注入Bean的几种方式?

  • Set 方法注入
  • 构造器注入:①通过index设置参数的位置;②通过type设置参数类型;
  • 静态工厂注入
  • 实例工厂。

8、怎样定义类的作用域?

答: 当定义一个在Spring里,我们还能给这个Bean声明一个作用域。它可以通过 Bean 定义中的 scope 属性来定义。如,当Spring要在需要的时候每次生产一个新的Bean实例,那么该Beanscope属性被指定为prototype。另一方面,如果一个Bean每次使用的时候必须返回同一个实例,这个Beanscope 属性必须设为singleton

9、解释Spring支持的几种Bean的作用域?

  • singleton Bean在每个Spring IOC 容器中只有一个实例。
  • prototype 一个Bean的定义可以有多个实例
  • request 每次http请求都会创建一个Bean,该作用域仅在基于 WebSpring ApplicationContext情形下有效。
  • session 在一个HTTP Session中,一个Bean定义对应一个实例。该作用域仅在基于 webSpring ApplicationContext情形下有效。
  • global-session 在一个全局的HTTP Session中,一个Bean定义对应一个实例。该作用域仅在基于 webSpring ApplicationContext情形下有效。

缺省的 Spring Bean 的作用域是 Singleton。使用 prototype 作用域需要慎重的思考,因为频繁创建和销毁 Bean 会带来很大的性能开销。

10、Spring框架中的单例Bean是线程安全的吗?

答: 不是,Spring框架中的单例Bean不是线程安全的。

Spring 中的Bean默认是单例模式,但是Spring框架并没有对单例 Bean 进行多线程的封装处理。实际上大部分时候 Spring Bean 无状态的(比如 dao 类),所有某种程度上来说 Bean 也是安全的,但如果 Bean 有状态的话(比如 view model 对象),那就要开发者自己去保证线程安全了,最简单的就是改变 Bean 的作用域,把“singleton”变更为“prototype”,这样请求 Bean 相当于 new Bean()了,所以就可以保证线程安全了。

  • 有状态就是有数据存储功能。
  • 无状态就是不会保存数据。

11、Spring如何处理线程并发问题?

答: 在一般情况下,只有无状态的 Bean 才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为作用域,因为 Spring 对一些 Bean 中非线程安全状态采用 ThreadLocal 进行处理,解决线程安全问题。ThreadLocal做了哪些工作:

  • ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了 “时间换空间” 的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。
  • ThreadLocal采用了 “空间换时间” 的方式。
  • ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal 提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal

12、解释Spring框架中Bean的生命周期?

答:BeanSpring容器中从创建到销毁经历了若干阶段,每一阶段都可以针对Spring如何管理Bean进行个性化定制。

Java——Spring得Bean详解(一文搞懂Spring的Bean)_第1张图片

  • Spring对Bean进行实例化
  • Spring将值和Bean的引用注入到 Bean 对应的属性中;
  • 如果Bean实现了BeanNameAware接口,Spring将BeanID传递给 setBean-Name() 方法;
  • 如果Bean实现了BeanFactoryAware接口,Spring将调用 setBeanFactory() 方法,将BeanFactory容器实例传入
  • 如果Bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将Bean所在的应用上下文的引用传入进来;
  • 如果Bean实现了BeanPostProcessor接口,Spring将调用它们的postProcessBeforeInitialization()方法;
  • 如果Bean实现了InitializingBean接口,Spring将调用它们的after-PropertiesSet()方法。类似地,如果Bean使用initmethod声明了初始化方法,该方法也会被调用;
  • 此时,Bean已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁
  • 如果Bean实现了DisposableBean接口,Spring将调用它的destroy()接口方法。同样,如果Bean使用 destroy-method 声明了销毁方法,该方法也会被调用。

13、哪些是重要的Bean生命周期方法? 你能重载它们吗?

答:

  • 有两个重要的Bean 生命周期方法,第一个是 setup(),它是在容器 加载 Bean 的时候被调用。第二个方法是 teardown() 它是在容器卸载类的时候被调用。
  • Bean 标签有两个重要的属性(init-methoddestroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct和@PreDestroy)。

14、什么是Spring的内部Bean?什么是Spring inner Beans

答:Spring框架中,当一个 Bean 仅被用作另一个 Bean 的属性时,它能被声明为一个内部Bean。内部Bean可以用setter注入“属性”和构造方法注入“构造参数”的方式来实现,内部Bean通常是匿名的,它们的Scope一般是prototype

15、在 Spring中如何注入一个Java集合?

答:

  • List 类型用于注入一列值,允许有相同的值。
  • Set 类型用于注入一组值,不允许有相同的值。
  • Map 类型用于注入一组键值对,键和值都可以为任意类型
  • Props 类型用于注入一组键值对,键和值都只能为 String 类型

16、什么是Bean装配?

答: 装配,或Bean装配是指在Spring 容器中把 Bean 组装到一起,前提是容器需要知道 Bean 的依赖关系,如何通过依赖注入来把它们装配到一起。

17、什么是Bean的自动装配

答:Spring框架中,在配置文件中设定 Bean 的依赖关系是一个很好的机制,Spring容器能够自动装配相互合作的Bean,这意味着容器不需要配置,能通过Bean工厂自动处理Bean之间的协作。这意味着Spring可以通过向BeanFactory中注入的方式自动搞定 Bean 之间的依赖关系。自动装配可以设置在每个Bean上,也可以设定在特定的Bean上。

18、解释不同方式的自动装配,Spring自动装配 Bean 有哪些方式?

答:Spring中,对象无需自己查找或创建与其关联的其他对象,由容器负责把需要相互协作的对象引用赋予各个对象,使用 Autowire 来配置自动装载模式

Spring框架xml配置中共有5种自动装配:

  • no默认的方式是不进行自动装配的,通过手工设置ref属性来进行装配Bean
  • byName 通过 Bean 的名称进行自动装配,如果一个Beanproperty 与另一Beanname 相同,就进行自动装配。
  • byType 通过参数的数据类型进行自动装配。
  • constructor 利用构造函数进行装配,并且构造函数的参数通过byType进行装配。
  • autodetect 自动探测,如果有构造方法,通过 construct的方式自动装配,否则使用byType的方式自动装配。

19、使用@Autowired注解自动装配的过程是怎样的?

答: 使用@Autowired注解来自动装配指定的Bean。在使用@Autowired注解之前需要在 Spring 配置文件进行配置,

在启动Spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied@Resource@Inject时,就会在IoC容器自动查找需要的Bean,并装配给该对象的属性

在使用@Autowired时:

  • 首先在容器中查询对应类型Bean
  • 如果查询结果刚好为一个,就将该Bean装配给@Autowired指定的数据;
  • 如果查询的结果不止一个,那么@Autowired会根据名称来查找;
  • 如果上述查找的结果为空,那么会抛出异常。解决方法时,使用required=false

你可能感兴趣的:(Java,java,spring,servlet)