IOC容器管理 bean

IOC容器管理 bean
Bean的命名以及实例化方法
Bean的命名

每一个交给Spring IOC(后面统称Spring容器)容器创建的对象必须被分配至少一个名称,如果开发者没有提供,Spring容器将会为其分配一个内部名称,通过Bean的名称,我们可以在其他类中查找该类并使用它,如前面的案例,也是通过Bean名称获取到实际对象并执行对应的操作。在基于xml的配置信息中,可以使用id属性来为一个Bean分配名称,在同一个xml配置文件中,id必须是唯一的,但不同的xml可以相同,当然还可以使用name来为Bean分配名称,name属性可以分配多个名称,此时可使用空格、逗号、分号来分离给定Bean分配多个名称,而id属性则无法这样使用。

<!-- name属性配置多个名称 -->
<bean name="accountDao,accountDao2" class="com.zejian.spring.springIoc.dao.impl.AccountDaoImpl"/>
<!-- id属性配置唯一名称而且不能与name相同-->
<bean id="accountDaoId" class="com.zejian.spring.springIoc.dao.impl.AccountDaoImpl"/>

在name属性中声明了两个名称,除了第一个名称外,其他的名称都被称为别名(aliase)。除了在Bean中定义名称外,还可利用<alias>标签向Bean赋予别名:

<bean id="accountDaoId" class="com.zejian.spring.springIoc.dao.impl.AccountDaoImpl"/>
<!-- name属性指明要给那个Bean赋予别名,alias则指明赋予的别名-->
<alias name="accountDaoId" alias="accountDao3" />

显然如果我们想要配置的Bean对象已存在,并且希望向一些Bean赋予特别的名称,此时别名就相当有用了。上述的Bean对象声明使用都在xml内声明手动声明的方式,一旦Bean对象多起来,管理Bean可能会发生繁琐的情况,为了Spring提供了基于Java注解的配置方式,下面分别使用org.springframework.stereotype.Service(@Service)和org.springframework.stereotype.Repository(@Repository)声明AccountServiceImpl和AccountDaoImpl类,使用@Autowired注解注入accountDao(需要在xml声明注解驱动)

//@Component 相同效果
@Service
public class AccountServiceImpl implements AccountService {
  @Autowired
  private AccountDao accountDao;
}

//@Component 相同效果
@Repository
public class AccountDaoImpl implements AccountDao{
//......
}

有了注解声明,我们就不需要在xml中声明以上两个Bean,但需要明确告诉Spring注解的Bean在那些包下,因此需要添加包扫描机制,此时需要启用Spring的context命名空间:
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        ">
    <!-- 声明包扫描 -->
    <context:component-scan base-package="com.zejian.spring.springIoc" />

</beans>

以上的声明方式与之前在xml声明bean的效果相同。这里我们需要明白可以使用@Component注解达到与@Service和@Repository的效果,@Component与@Service的含义并无差异,只不过@Service更能让我们明白该类为业务类罢了。至于@Repository在表示数据访问层含义的同时还能够启用与Spring数据访问相关链的其他功能(这个在Spring jdbc相关内容时再详谈,此时我们只需明白@Repository与@Component等效即可),同时还可给@Component、@Service和@Repository输入一个String值的名称,如果没有提供名称,那么默认情况下就是一个简单的类名(第一个字符小写)变成Bean名称。

@Service("accountService")
public class AccountServiceImpl implements AccountService {
  @Autowired
  private AccountDao accountDao;
}

@Repository("accountDao")
public class AccountDaoImpl implements AccountDao{
//......
}

因此到这我们也就知道了,Spring的框架中提供了与@Component注解等效的三个注解,@Repository 用于对DAO实现类进行标注,@Service 用于对Service实现类进行标注,@Controller 用于对Controller实现类进行标注(web层控制器),同时也了解了Spring 容器通过xml的bean标签配置和java注解两种方式声明的Bean对象,我们可以单独使用其中一种也可以两种混合使用,取决于各自的需求。


 Bean的重写机制

 

Bean的重写机制并没有那么神秘,主要是当不同的xml文件中出现同名id属性的bean时读取的优先级问题,同样简单看个例子就明白了。定义两个spring的配置文件并同时加载它们:spring-ioc.xml

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 默认构造创建,并通过property 注入属性值 -->
<bean id="account" class="com.zejian.spring.springIoc.pojo.Account" >
    <property name="name" value="I am SpringIOC1" />
    <property name="pwd" value="123" />
</bean>
</beans>

spring-ioc2.xml

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 默认构造创建,并通过property 注入属性值 -->
<bean id="account" class="com.zejian.spring.springIoc.pojo.Account" >
    <property name="name" value="I am SpringIOC2" />
    <property name="pwd" value="123" />
</bean>
</beans>

获取bean并调用

@Test
public void test1()  {
  ApplicationContext applicationContext=new
          ClassPathXmlApplicationContext("spring/spring-ioc.xml","spring/spring-ioc2.xml");
    Account account= (Account) applicationContext.getBean("account");
    System.out.println("调用结果:"+account.getName());
}

显然在不同的xml配置文件中使用相同id命名,并声明相同类型的bean对象时,spring容器会默认加载最后添加的spring-ioc2.xml中account而忽略spring-ioc.xml中的account,也就是说Bean的重写机制原则是当声明的bean的名称一样时,后者会覆盖前者。我们还需要明确的一点时,在web应用开发过程中,一般都会将配置进行分层管理,然后通过一个主springApplication.xml来聚合它,在这样的情况下分层的配置文件属于springApplication.xml的子文件,在这样的关系遇到上述的情况一般都子文件的优先级高,因此会加载子文件的bean。如在spring-ioc.xml主文件导入子文件spring-ioc2.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        ">

    <!-- 默认构造创建,并通过property 注入属性值 -->
    <bean id="account" class="com.zejian.spring.springIoc.pojo.Account" >
        <property name="name" value="I am SpringIOC1" />
        <property name="pwd" value="123" />
    </bean>

    <!-- 导入的子文件 -->
    <import resource="spring-ioc2.xml" />
</beans>

运行代码:

@Test
  public void test1()  {
    ApplicationContext applicationContext=new
            ClassPathXmlApplicationContext("spring/spring-ioc.xml");
      Account account= (Account) applicationContext.getBean("account");
      System.out.println("调用结果:"+account.getName());
  }

上述代码会优先加载spring-ioc2.xml中的account而忽略spring-ioc.xml中的account,效果与前面的代码相同。

Spring IOC容器创建一个Bean实例时,可以为Bean指定实例的作用域,作用域包括singleton(单例模式)、prototype(原型模式)、request(HTTP请求)、session(会话)、global-session(全局会话)。

 Bean的延长加载

在某些情况下,我们可能希望把bean的创建延迟到使用阶段,以免消耗不必要的内存,Spring也非常自愿地支持了延迟bean的初始化。因此可以在配置文件中定义bean的延迟加载,这样Spring容器将会延迟bean的创建直到真正需要时才创建。通常情况下,从一个已创建的bean引用另外一个bean,或者显示查找一个bean时会触发bean的创建即使配置了延迟属性,因此如果Spring容器在启动时创建了那些设为延长加载的bean实例,不必惊讶,可能那些延迟初始化的bean可能被注入到一个非延迟创建且作用域为singleton的bean。在xml文件中使用bean的lazy-init属性可以配置改bean是否延迟加载,如果需要配置整个xml文件的bean都延迟加载则使用defualt-lazy-init属性,请注意lazy-init属性会覆盖defualt-lazy-init属性。

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        " default-lazy-init="true">
    <!--default-lazy-init="true" xml中全部bean延迟加载 -->
    <!-- lazy-init="false" 表示非延长加载-->
    <bean name="accountDao" lazy-init="false"
          class="com.zejian.spring.springIoc.dao.impl.AccountDaoImpl"/>

    <!-- 声明accountService对象,交给spring创建 -->
    <bean name="accountService" class="com.zejian.spring.springIoc.service.impl.AccountServiceImpl">
          <!-- 注入accountDao对象,需要set方法-->
          <property name="accountDao" ref="accountDao"/>
    </bean>
</beans>

默认情况下Spring容器在启动阶段就会创建bean,这个过程被称为预先bean初始化,这样是有好处的,可尽可能早发现配置错误,如配置文件的出现错别字或者某些bean还没有被定义却被注入等。当然如存在大量bean需要初始化,这可能引起spring容器启动缓慢,一些特定的bean可能只是某些场合需要而没必要在spring容器启动阶段就创建,这样的bean可能是Mybatis的SessionFactory或者Hibernate SessionFactory等,延迟加载它们会让Spring容器启动更轻松些,从而也减少没必要的内存消耗。

<context:component-scan/>与<context:annotation-config/>

前面我们使用@Autowired、@Resource、@Value等自动装配注解时用<context:annotation-config/>进行注解驱动注册,从而使注解生效。实际上这样<context:annotation-config/>一条配置,它的作用是式地向 Spring 容器注册AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor 以及RequiredAnnotationBeanPostProcessor 这 4 个BeanPostProcessor。注册这4个 BeanPostProcessor后Spring容器就能够识别相应的注解了,当然它们也是也可单独配置的。 
假如想使用@ Resource 、@ PostConstruct、@ PreDestroy等注解就可以单独声明CommonAnnotationBeanPostProcessor 
如果想使用@PersistenceContext注解,声明PersistenceAnnotationBeanPostProcessor的Bean即可。 
如果想使用 @Required的注解,就必须声明RequiredAnnotationBeanPostProcessor的Bean。 
一般来说,这些注解是随处可见的,如果总是需要一条一条配置自然就非常繁琐了,于是spring容器非常智能地为我们提供<context:annotation-config/>的简化配置方式,自动声明。 
对于<context:component-scan/>,前面在使用@Service、@Component、@Controller

、@Repository等注解时,需要在xml配置文件声明包扫描驱动<context:component-scan/>,它的作用是Spring容器在启动时会启动注解驱动去扫描对应包下的bean对象并将创建它们的实例,这样我们就无法一个个地进行bean配置声明了,极大简化了编程代码。请注意,当spring的xml配置文件出了<context:component-scan/>

后,<context:annotation-config/>就可以退休了,因为<context:component-scan/>已包含了<context:annotation-config/>的功能了。在大部分情况下,都会直接使用<context:component-scan/>进行注解驱动注册和包扫描功能。

原文地址:https://www.cnblogs.com/hellohero55/p/12649993.html

时间: 2024-08-12 09:28:21

IOC容器管理 bean的相关文章

IOC容器中bean的生命周期

一.Bean生命周期 Spring IOC容器可以管理Bean的生命周期,允许在Bean生命周期的特定点执行定制的任务. Spring IOC容器对Bean的生命周期进行管理的过程如下: 通过构造器或工厂方法创建Bean实例 为Bean的属性设置值和对其它Bean的引用 调用Bean的初始化方法 Bean可以使用了 当容器关闭时,调用Bean的销毁方法 在 Bean 的声明里设置 init-method 和 destroy-method 属性, 为 Bean 指定初始化和销毁方法. 下面通过示例

[原创]java WEB学习笔记101:Spring学习---Spring Bean配置:IOC容器中bean的声明周期,Bean 后置处理器

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

Spring核心技术之IOC容器(一):IOC容器与Bean简介

最近开始研究Spring框架,今天学习Spring的核心内容IOC 与 Bean 1. Spring IOC 与 Bean 简介  Inversion of Control (IoC)即控制反转,也叫dependency injection (DI)依赖注入,Spring实现了一个基于配置文件的复杂工厂模式来提供实现控制反转. org.springframework.beans 和org.springframework.context包是Spring中实现IOC的基础包,其中BeanFactor

IOC容器中Bean的生命周期方法

一Spring IOC容器可以管理Bean的生命周期,Spring允许在Bean生命周期的特定点执行定制的任务. 二.Spring IOC容器对Bean的生命周期进行管理的过程: -通过构造器或工厂方法创建Bean的实例 -为Bean的属性设置值和对其他的Bean的引用 -调用Bean的初始化方法 -Bean可以用了 -当容器关闭是吗,调用Bean的销毁方法 三.在bean的声明里设置init-method和destroy-method属性.为Bean指定初始化和销毁方法.

Spring框架—— IOC容器和Bean的配置

 1 IOC和DI ①IOC(Inversion of Control):反转控制. 在应用程序中的组件需要获取资源时,传统的方式是组件主动的从容器中获取所需要的资源,在这样的模式下开发人员往往需要知道在具体容器中特定资源的获取方式,增加了学习成本,同时降低了开发效率. 反转控制的思想完全颠覆了应用程序组件获取资源的传统方式:反转了资源的获取方向--改由容器主动的将资源推送给需要的组件,开发人员不需要知道容器是如何创建资源对象的,只需要提供接收资源的方式即可,极大的降低了学习成本,提高了开发的效

JAVAWEB开发之Spring详解之——Spring的入门以及IOC容器装配Bean(xml和注解的方式)、Spring整合web开发、整合Junit4测试

Spring框架学习路线 Spring的IOC Spring的AOP,AspectJ Spring的事务管理,三大框架的整合 Spring框架概述 什么是Spring? Spring是分层的JavaSE/EE full-stack(一站式)轻量级开源框架. 所谓分层: SUN提供的EE的三层结构:web层.业务层.数据访问层(也称持久层,集成层). Struts2是web层基于MVC设计模式框架. Hibernate是持久的一个ORM的框架. 所谓一站式:Spring框架有对三层的每层解决方案.

Spring核心技术(一)——IoC容器和Bean简介

IoC容器和Bean简介 这章包括了Spring框架对于IoC规则的实现.Ioc也同DI(依赖注入).而对象是通过构造函数,工厂方法,或者一些Set方法来定义对象之间的依赖的.容器在创建这些Bean对象的时候同时就会注入这些依赖.这个过程是根本上的反转了,不再由Bean本身来控制实例化和定位依赖,而是通过服务定位来控制这个过程,也是IoC(控制反转)的由来. org.springframework.beans和org.springframework.context包是Spring框架IoC容器的

介绍 Spring IoC 容器和 bean

简介 本章涵盖了 Spring Framework实现控制翻转 (IoC) 的原则. IoC 有时也被称为依赖注入 (DI).这是一个对象定义他们依赖的过程,其中对象之间的相关性,也就是说,它们一起工作,只能通过构造函数参数,参数工厂方法或设置在其构造后的对象实例或者是从一个工厂方法返回的对象实例的属性上.容器在创建的 bean 注入这些依赖.这个过程是根本的反转,因此称为控制反转(IoC),bean 本身通过直接构造类,或作为 Service Locator(服务定位器)模式的机制,来控制其依

Spring IoC容器管理Action

Spring IoC容器管理Action有两种方式:DelegatingRequestProcessor.DelegatingActionProxy 不管采用哪一种方式,都需要随应用启动时创建ApplicationContext实例,由Struts负责在应用启动时创建ApplicationContext实例.Struts中提供了PlugIn的扩展点,可在应用启动和关闭时,创建或销毁某些资源. 使用ContextLoaderPluIn创建了ApplicationContext实例后,关键是如何将A