飙血推荐
  • HTML教程
  • MySQL教程
  • JavaScript基础教程
  • php入门教程
  • JavaScript正则表达式运用
  • Excel函数教程
  • UEditor使用文档
  • AngularJS教程
  • ThinkPHP5.0教程

深入理解Spring IOC容器

时间:2021-12-04  作者:javammc  

本文将从纯xml模式、xml和注解结合、纯注解的方式讲解Spring IOC容器的配置和相关应用。

纯XML模式

实例化Bean的三种方式

  1. 使用无参构造函数

默认情况下,会使用反射调用无参构造函数来创建对象。

<bean id="connectionUtils" class="域名.域名ectionUtils"></bean>
  1. 使用静态方法创建

在实际开发中,我们使用的方法有时候不是通过构造函数创建出来的,他可能在创建的时候会做很多额外的操作。此时会提供一个创建对象的方法,如果这个方法是static修饰的,就是用这种配置方式。

<bean id="druidUtils" class="域名.域名dUtils" factory-method="getInstance"></bean>
  1. 使用实例化方法创建

当方法不是静态的时候,用这种方式

 <bean id="connectionUtils" class="域名.域名ectionUtils"></bean>
 <bean id="account" factory-bean="connectionUtils" factory-method="createAccount"></bean>

bean的作用范围和声明周期

常用的是singleton【默认】(单例模式)和prototype(原型模式或多例模式)。通过scope属性可以进行配置

<bean id="account" factory-bean="connectionUtils" factory-method="createAccount" scope="singleton"></bean>

不同作用范围的生命周期

单例模式:singleton

对象创建:当创建容器时,对象就被创建

对象活着:只要容器在,对象一直活着

对象死亡:当容器销毁,对象就被销毁

总结:单例模式的bean对象生命周期与容器相同

多例模式:prototype

对象创建:当使用对象时,创建新的对象实例

对象活着:只要对象在使用中,就一直活着

对象死亡:当对象长时间不用时,被垃圾回收器回收

总结:多例模式的bean对象,spring框架只负责创建,不负责销毁。

Bean的标签属性

  • id属性: ⽤于给bean提供⼀个唯⼀标识。在⼀个标签内部,标识必须唯⼀。
  • class属性:⽤于指定创建Bean对象的全限定类名。
  • name属性:⽤于给bean提供⼀个或多个名称。多个名称⽤空格分隔。
  • factory-bean属性:⽤于指定创建当前bean对象的⼯⼚bean的唯⼀标识。当指定了此属性之后,
    class属性失效。
  • factory-method属性:⽤于指定创建当前bean对象的⼯⼚⽅法,如配合factory-bean属性使⽤,
    则class属性失效。如配合class属性使⽤,则⽅法必须是static的。
  • scope属性:⽤于指定bean对象的作⽤范围。通常情况下就是singleton。当要⽤到多例模式时,
    可以配置为prototype。
  • init-method属性:⽤于指定bean对象的初始化⽅法,此⽅法会在bean对象装配后调⽤。必须是
    ⼀个⽆参⽅法。
  • destory-method属性:⽤于指定bean对象的销毁⽅法,此⽅法会在bean对象销毁前执⾏。它只
    能为scope是singleton时起作⽤。

DI依赖注入

  1. 按照注入的方式分类
  • 构造函数注入:就是利用带参构造函数实现对类成员的属性赋值
<bean id="account" class="域名.域名unt">
        <constructor-arg name="cardNo" value="123"></constructor-arg>
        <constructor-arg name="money" value="23"></constructor-arg>
        <constructor-arg name="name" value="aa"></constructor-arg>
    </bean>
  • set方法注入:通过类成员的set方法实现数据注入
 <bean id="account" class="域名.域名unt">
        <property name="name" value="mmc"></property>
        <property name="cardNo" value="abc"></property>
        <property name="money" value="22"></property>
    </bean>
  1. 按照注入的数据类型分类
  • 基本数据类型和String
  • 其他Bean类型
  • 复杂类型(集合类型)

基本类型使用value,其他bean类型使用ref,复杂类型使用对应的array、map、set标签

<bean id="user" class="域名.域名">
        <property name="id" value="1"></property>
        <property name="account" ref="account"></property>
        <property name="list">
            <array>
                <value>aa</value>
                <value>bb</value>
            </array>
        </property>
        <property name="map">
            <map>
                <entry key="a" value="1"></entry>
                <entry key="b" value="2"></entry>
            </map>
        </property>
    </bean>

域名

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://域名/dtd/web-域名" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <!--配置spring ioc容器的配置文件-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:域名</param-value>
  </context-param>


  <!--使用监听器启动Spring的IOC容器-->
  <listener>
    <listener-class>域名.域名extLoaderListener</listener-class>
  </listener>
</web-app>

xml与注解结合的方式

注意:实际开发中,纯xml模式使用已经很少了,引入注解功能,不需要引入额外的jar包。xml+注解结合模式中,xml文件依然存在,所以Spring IOC容器的启动仍然从加载xml开始。

一般来说第三方jar包里面的bean定义在xml里面,自己开发的bean使用注解。

将第三方jar包的bean放入容器

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://域名/schema/beans"
       xmlns:xsi="http://域名/2001/XMLSchema-instance"
       xmlns:context="http://域名/schema/context"
       xsi:schemaLocation="http://域名/schema/beans
        https://域名/schema/beans/spring-域名
    http://域名/schema/context
       https://域名/schema/context/spring-域名
">

    <!--包扫描-->
    <context:component-scan base-package="域名"></context:component-scan>

    <!--引入配置文件-->
    <context:property-placeholder location="classpath:域名erties"></context:property-placeholder>


    <bean id="dataSource" class="域名域名dDataSource">
        <property name="driverClassName" value="${域名er}"></property>
        <property name="url" value="${域名}"></property>
        <property name="username" value="${域名name}"></property>
        <property name="password" value="${域名word}"></property>
    </bean>


</beans>

xml中标签与注解的对应

xml形式 注解
标签 @Component,注解加在类上。默认情况下bean的id为类名(首字母小写)。另外,针对分层代码开发提供了@Componenet的三种别名@Controller、

@Service、@Repository分别⽤于控制层类、服务层类、dao层类的bean定义,这
四个注解的⽤法完全⼀样,只是为了更清晰的区分⽽已
标签的scope属性 | @Scope("prototype")

DI依赖注入的注解实现方式

  1. @Autowired(推荐使用)

@Autowired为Spring提供的注解。策略是按类型注入

public class TransferServiceImpl implements TransferService {

    @Autowired
    private AccountDao accountDao;

}

如上代码所示,这样装配会去spring容器中找到类型为AccountDao的bean,然后将其中如。但如果一个类型有多个bean怎么办呢?可以配合@Qualifier("bean的id")使用。

public class TransferServiceImpl implements TransferService {

    @Autowired
    @Qualifier("jdbcAccountDao")
    private AccountDao accountDao;
}
  1. @Resource

@Resource注解由j2EE提,如果指定了name或type就会根据指定的来,如果都没有指定就自动按照ByName方式装配

注意:@Resource在Jdk11中已经移除,如果要使用,需要单独引入jar包。

<dependency>
    <groupId>域名tation</groupId>
    <artifactId>域名tation-api</artifactId>
    <version>1.3.2</version>
</dependency>

在Servlet类里面获取applicationContext

public class TransferServlet extends HttpServlet {

  

    @Override
    public void init() throws ServletException {
        WebApplicationContext webApplicationContext = 域名ebApplicationContext(域名ervletContext());
        ProxyFactory proxyFactory = (ProxyFactory) 域名ean("proxyFactory");
        transferService= (TransferService) 域名dkProxy(域名ean("transferService"));
    }
}

纯注解模式

将xml配置改为java代码:

在配置类上声明@Configuration,表明是配置类。

@Configuration
@ComponentScan("域名")
@PropertySource("classpath:域名erties")
public class SpringConfig {


    @Value("${域名er}")
    private String driverClass;

    @Value("${域名}")
    private String url;

    @Value("${域名name}")
    private String username;

    @Value("${域名word}")
    private String password;


    @Bean
    public DataSource dataSource(){
        DruidDataSource druidDataSource=new DruidDataSource();
        域名riverClassName(driverClass);
        域名rl(url);
        域名sername(username);
        域名assword(password);
        return druidDataSource;
    }
}

如果还有其他配置类,可以通过@Import引入进来。

域名配置如下:

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://域名/dtd/web-域名" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

   <!--告诉ContextLoaderListener是注解方式启动ioc容器-->
   <context-param>
     <param-name>contextClass</param-name>
     <param-value>域名.域名tationConfigWebApplicationContext</param-value>
   </context-param>


  <!--配置spring ioc容器的配置文件-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>域名.SpringConfig</param-value>
  </context-param>


  <!--使用监听器启动Spring的IOC容器-->
  <listener>
    <listener-class>域名.域名extLoaderListener</listener-class>
  </listener>
</web-app>

高频面试题:

BeanFactory、FactoryBean、ApplicationContext的区别

  • BeanFactory是Spring框架中IOC容器的顶层接口,它只是用来定义一些基础功能
  • ApplicationContext是它的一个子接口,它拥有更多的功能,如国际化支持和资源访问等等。
  • FactoryBean:一般情况下,Spring通过反射机制实例化Bean,在某些情况下,实例化bean过程比较复杂,这时配置起来就比较麻烦。如果采用编码的方式会简单一些。于是Spring给我们提供了FactoryBean的接口,用户就可以通过实现这个接口来自定义实例化Bean的逻辑。

总结:BeanFactory是负责生产和管理Bean的一个工厂接口,提供一个Spring Ioc容器规范。FactoryBean是一种Bean创建的方法,对Bean的一种扩展。

类图如下:

标签:编程
湘ICP备14001474号-3  投诉建议:234161800@qq.com   部分内容来源于网络,如有侵权,请联系删除。