Spring 04 Spring 配置扩展

10 篇文章 0 订阅

Spring 配置扩展

一、学习目标
  1. 掌握更多配置数据源的方法
  2. 理解Bean的作用域
  3. 掌握Bean的自动装配功能
  4. 掌握在项目中使用多个Spring配置文件的方法
二、使用properties文件配置数据源
2.1、PropertyPlaceholderConfigurer的作用
  • 这个类的作用是把我们配置文件中或者代码中的${ }占位符替换为properties文件中的配置
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
	<property name="location" value="classpath:db.properties" />
</bean>
  • 只需要指定配置文件的路径即可,会自动把ioc容器中的占位符替换为对应配置

原理:

  • PropertyPlaceholderConfigurer 主要是使用到了Spring的BeanFactoryPostProcessorpostProcessBeanFactory回调。

  • 这个回调方法会在BeanFactory初始化并且加载好BeanDefinition后执行,但会在所有Bean初始化之前。PropertyPlaceholderConfigurer中回调的主要逻辑就是遍历BeanDefinition,对占位符进行替换。

我们先看下PropertyPlaceholderConfigurer的类继承图

在这里插入图片描述

  • 可以看到PropertyResourceConfigurer继承了BeanFactoryPostProcessor接口,我们从它的postProcessBeanFactory方法看起
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  try {
      Properties mergedProps = mergeProperties();

      // Convert the merged properties, if necessary.
      convertProperties(mergedProps);

      // Let the subclass process the properties.
      processProperties(beanFactory, mergedProps);
  }
  catch (IOException ex) {
      throw new BeanInitializationException("Could not load properties", ex);
  }
}
  • 这边有三个步骤,mergeProperties方法merge操作基本没有,主要是用来从硬盘加载properties文件。

  • convertProperties用来对PropertyValue做一些自定义转换,默认是返回原值,所以这个方法忽略即可。

  • processProperties是具体的propeties替换逻辑,交给子类实现,PropertyPlaceholderConfigurer的实现如下。

protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
  	StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props);
  doProcessProperties(beanFactoryToProcess, valueResolver);
}
  • PlaceholderResolvingStringValueResolver封装了通过占位符从配置文件获取对应配置的逻辑,我们基本可以认为{a.b}可以更复杂,比如{a.b}.${c.d}这种复杂的情况。

  • 遍历BeanDefinition对占位符进行替换的逻辑则封装在doProcessProperties方法中,这个实现在父类PlaceholderConfigurerSupport中实现

protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
      StringValueResolver valueResolver) {

  BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);

  String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
  for (String curName : beanNames) {
      // Check that we're not parsing our own bean definition,
      // to avoid failing on unresolvable placeholders in properties file locations.
      if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) {
          BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName);
          try {
              visitor.visitBeanDefinition(bd);
          }
          catch (Exception ex) {
              throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage(), ex);
          }
      }
  }

  // New in Spring 2.5: resolve placeholders in alias target names and aliases as well.
  beanFactoryToProcess.resolveAliases(valueResolver);

  // New in Spring 3.0: resolve placeholders in embedded values such as annotation attributes.
  beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
}
  • 基本逻辑和描述的差不多,BeanDefinitionVisitor封装了操作BeanDefiniton逻辑,对占位符进行替换
public void visitBeanDefinition(BeanDefinition beanDefinition) {
  visitParentName(beanDefinition);
  visitBeanClassName(beanDefinition);
  visitFactoryBeanName(beanDefinition);
  visitFactoryMethodName(beanDefinition);
  visitScope(beanDefinition);
  visitPropertyValues(beanDefinition.getPropertyValues());
  ConstructorArgumentValues cas = beanDefinition.getConstructorArgumentValues();
  visitIndexedArgumentValues(cas.getIndexedArgumentValues());
  visitGenericArgumentValues(cas.getGenericArgumentValues());
}
  • 可以看到占位符可以出现在以上这些地方。不过我们一般使用在PropertyValue中。

总结:

  • 其实配置文件替换bean的属性的原理挺简单,就是通过BeanFactoryPostProcessor在bean初始化之前,加载Beanfinition之后对Beanfinition中的占位符进行替换
  • 分析这个类的主要目的是,因为Disconf动态配置,就是在这个类的基础上修改实现的。
2.2、使用properties文件配置数据源

步骤

  1. 数据源的相关配置信息放到properties文件中维护

  2. 采用PropertySourcesPlaceholderConfigurer类加载properties文件

  3. Spring配置文件中采用${xxx}方式引用properties文件中的键值对数据


2.2.1properties配置
  • 注意username的名字不能直接使用username可以使用jdbc.username或者其他名称,同时注意要删除原先url中(amp;)的字符不然报红红。
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/cvs_db?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=root
2.2.2maven配置需要引入dbcp包
<!--引入dbcp-->
<dependency>
    <groupId>commons-dbcp</groupId>
    <artifactId>commons-dbcp</artifactId>
    <version>1.4</version>
</dependency>
2.2.3spring配置
<?xml version="1.0" encoding="UTF-8"?>
<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-3.2.xsd   http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 1.引入数据库连接信息配置文件-->
    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <property name="location" value="classpath:database.properties"></property>
    </bean>

    <!--2.配置数据源-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
    <!--3.注入SqlSessionFactoryBean-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--配置数据源-->
        <property name="dataSource" ref="dataSource"></property>
        <!-- 配置别名-->
        <property name="typeAliasesPackage" value="com.aiden.mybatisspring.pojo"></property>
        <!--引用mybatis核心配置文件-->
        <property name="configLocation" value="classpath:mybatis-config2.xml"></property>
        <!-- 配置mapper映射文件-->
        <property name="mapperLocations">
            <list>
                <value>com/aiden/mybatisspring/mapper/*.xml</value>
            </list>
        </property>
    </bean>
    <!-- 4.注入SqlSessionTemplate-->
    <bean class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
    </bean>
</beans>
2.2.4配置数据源详细参数
  • BasicDataSource提供了close()方法关闭数据源,所以必须设定==destroy-method=”close”==属性, 以便Spring容器关闭时,数据源能够正常关闭。除以上必须的数据源属性外,还有一些常用的属性:
  • defaultAutoCommit:设置从数据源中返回的连接是否采用自动提交机制,默认值为 true;
  • defaultReadOnly:设置数据源是否仅能执行只读操作, 默认值为 false;
  • maxActive:最大连接数据库连接数,设置为0时,表示没有限制;
  • maxIdle:最大等待连接中的数量,设置为0时,表示没有限制;
  • maxWait:最大等待秒数,单位为毫秒, 超过时间会报出错误信息;
  • validationQuery:用于验证连接是否成功的查询SQL语句,SQL语句必须至少要返回一行数据, 如你可以简单地设置为:“select count(*) from user”;
  • removeAbandoned:是否自我中断,默认是 false ;
  • removeAbandonedTimeout:几秒后数据连接会自动断开,在removeAbandoned为true,提供该值;
  • logAbandoned:是否记录中断事件, 默认为 false;
三、使用JNDI配置数据源
3.1在服务器容器中配置数据源
  • 把数据库驱动文件放到Tomcat的lib目录下

  • 修改Tomcat的conf目录下的context.xml文件

  • context.xml配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <Context>
        <WatchedResource>WEB-INF/web.xml</WatchedResource>
        <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
        <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
    	
    	<Resource   
            name="jdbc/cvs_db"  
            auth="Container"   
            type="javax.sql.DataSource"  
            maxTotal="100"   
            maxIdle="30"   
            maxWaitMillis="10000"  
            username="root"   
            password="root"  
            driverClassName="com.mysql.cj.jdbc.Driver"  
            url="jdbc:mysql://127.0.0.1:3306/cvs_db?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=Asia/Shanghai"/>
    </Context>
    
3.2在Spring配置文件中引用JNDI资源
<!--通过JNDI配置DataSource-->
<bean id="dataSource"
	class="org.springframework.jndi.JndiObjectFactoryBean">
	<!--通过jndiName指定引用的JNDI数据源名称-->
	<property name="jndiName">
		<value>java:comp/env/jdbc/cvs_db</value>
	</property>
</bean>
3.3创建servlet
<dependencies>
  <!-- 需要引入.servlet-api依赖包 -->
  <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>javax.servlet-api</artifactId>
       <version>3.1.0</version>
  </dependency>
</dependencies>
package cn.cvs.servlet; 
/**
 * SysUserServlet类
*
 * @author Aiden
*/
import cn.cvs.pojo.SysUser;
import cn.cvs.service.SysUserService;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

@WebServlet("/SysUserServlet")
public class SysUserServlet extends HttpServlet {
 private Logger logger = Logger.getLogger(SysUserServlet.class);
 /**
     * 处理客户端请求 
  */
 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     //设置编码格式
     request.setCharacterEncoding("utf-8");
     response.setContentType("text/html;charset=UTF-8");
     ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
     SysUserService sysUserService = context.getBean("sysUserServiceImpl", SysUserService.class);
     List<SysUser> userList = sysUserService.selectUserList();
     request.setAttribute("userList",userList);
     request.getRequestDispatcher("index.jsp").forward(request,response);
 }

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     doPost(request, response);
 }
}
3.4创建index.jsp页面
<%@ page import="cn.cvs.pojo.SysUser" %>
<%@ page import="java.util.List" %>
<%--
User: Aiden
Date: 2021-12
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
 <title>使用JNDI配置数据源</title>
</head>
<body>
<%
 List<SysUser> userList = (List<SysUser>) request.getAttribute("userList");
 for (SysUser sysUser : userList) {
%>
    <p><%=sysUser.getRealName()%></p>
<% }%>
</body>
</html>
3.5设置配置tomcat

在这里插入图片描述

3.6设置工件

(需要创建lib目录,并添加所需要的的依赖包)

在这里插入图片描述

3.7启动运行
  • 访问运行地址: http://localhost:8080/study_spring04/SysUserServlet

在这里插入图片描述

3.8注意事项
  1. 要测试JNDI方式配置数据源功能,需在Web环境下进行
  2. 可将测试代码编写在Servlet中,通过浏览器访问Servlet进行测试
3.9总结归纳
  • JNDI配置DataSource使用方式需要在web server中配置数据源,不方便于部署
四、拆分Spring配置文件
4.1、拆分Spring配置文件

问题

  • 为什么要拆分Spring配置文件?
    • 项目规模变大,配置文件可读性和维护性都会降低
    • 多人修改同一配置文件时也容易发生冲突,影响开发效率 Git SVN

分析

  • 拆分方案
    • 公用配置(包含数据源、事务等)+每个系统模块一个单独配置文件(包含Dao、Service以及Web控制器)
    • 公用配置(包含数据源、事务等)+DAO Bean配置+业务逻辑Bean配置+Web控制器配置
    • 两种方案各有特色,适用于不同场合
4.2、引入拆分后的配置文件

两种方法

  • 利用ClassPathXmlApplicationContext类的重载方法配置多个配置文件,用逗号隔开或者使用通配符
public ClassPathXmlApplicationContext(String configLocation);
// 以String[]方式传入多个配置文件名
public ClassPathXmlApplicationContext(String… configLocations);
  • 在Spring配置文件中使用import标签加载多个配置文件
<import resource="applicationContext-dao.xml" />
<import resource="applicationContext-service.xml" />

演示示例3:拆分Spring配置文件

  1. 创建applicationContext-dao.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    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
 http://www.springframework.org/schema/tx
 http://www.springframework.org/schema/tx/spring-tx.xsd
 http://www.springframework.org/schema/aop
 http://www.springframework.org/schema/aop/spring-aop.xsd">

 <!-- mapper配置扫描 -->
 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
     <property name="basePackage" value="cn.cvs.dao" />
 </bean>
</beans>
  1. 创建applicationContext-service.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    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
 http://www.springframework.org/schema/tx
 http://www.springframework.org/schema/tx/spring-tx.xsd
 http://www.springframework.org/schema/aop
 http://www.springframework.org/schema/aop/spring-aop.xsd">

 <!-- 配置业务Bean -->
 <context:component-scan base-package="cn.cvs.service" />
</beans>
  1. applicationContext.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<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"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    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
 http://www.springframework.org/schema/tx
 http://www.springframework.org/schema/tx/spring-tx.xsd
 http://www.springframework.org/schema/aop
 http://www.springframework.org/schema/aop/spring-aop.xsd">

 <!--在Spring配置文件中使用import标签加载多个配置文件-->
 <import resource="classpath:applicationContext-dao.xml"></import>
 <import resource="classpath:applicationContext-service.xml"></import>

 <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
     <property name="location" value="classpath:db.properties"></property>
 </bean>

 <!--  1.配置Spring管理数据源(DBCP) destroy-method=”close”的作用是当数据库连接不使用的时候,就把该连接重新放到数据池中,方便下次使用调用 -->
 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
     <property name="driverClassName" value="${jdbc.driver}"></property>
     <property name="url"  value="${jdbc.url}"></property>
     <property name="username" value="${jdbc.username}"></property>
     <property name="password" value="${jdbc.password}"></property>
 </bean>
 <!-- 2.配置SqlSessionFactoryBean 创建对象的过程全部交给spring来做-->
 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
     <!--2.1配置数据源组件-->
     <property name="dataSource" ref="dataSource"></property>
     <!--2.2配置别名-->
     <property name="typeAliasesPackage" value="cn.cvs.pojo"></property>
     <!--2.3配置mapper映射文件的位置-->
     <property name="mapperLocations" value="classpath:cn/cvs/mapper/*Mapper.xml"></property>
     <!--2.4可直接引入mybatis配置文件-->
     <property name="configLocation" value="classpath:mybatis-config.xml"></property>
 </bean>
 <!-- 3.配置SqlSessionTemplate-->
 <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
     <constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
 </bean>

</beans>
五、Spring中Bean的自动装配
5.0、为什么使用自动装配

回顾前面的学习中所编写的代码,使用配置文件装配Bean组件,需要通过property标签手动为每个属性注入所依赖的对象,关键代码如下:

<!--1.配置数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driver}"></property>
    <property name="url" value="${jdbc.url}"></property>
    <property name="username" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>

<!--2.注入SqlSessionFactoryBean-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
     <!--配置数据源-->
     <property name="dataSource" ref="dataSource"></property>
     <!-- 配置别名-->
     <property name="typeAliasesPackage" value="com.aiden.mybatisspring.pojo"></property>
     <!--引用mybatis核心配置文件-->
     <property name="configLocation" value="classpath:mybatis-config.xml"></property>
     <!-- 配置mapper映射文件-->
     <property name="mapperLocations">
        <list>
            <value>com/aiden/mybatisspring/mapper/*.xml</value>
        </list>
     </property>
</bean>
<!--3.SysUserMapperImpl-->
<bean id="sysUserMapper" class="cn.cvs.service.mapper.SysUserMapperImpl">
	<property name="sqlSessionFactory" ref="sqlSessionFactory">
</bean>
 <!--4.SysUserServiceImpl-->   
<bean id="userService" class="cn.cvs.service.SysUserServiceImpl">
	<property name="sysUserMapper" ref="sysUserMapper">
</bean>

随着业务的发展,项目规模越来越大,需要在配置文件中维护的Ben组件注入的属性也越来越多,这不仅给开发人员带来了大量的工作,还让系统变得难以维护,这时候就需要使用自动装配的方式来解决问题了

5.1、Bean的自动装配

自动装配说明

  • 自动装配是使用spring满足bean依赖的一种方法
  • spring会在应用上下文中为某个bean寻找其依赖的bean。

Spring中bean三种装配机制

  1. 在xml中显式配置;
  2. 在java中显式配置;
  3. 隐式的bean发现机制和自动装配

Spring的自动装配需要从两个角度来实现

  1. 组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;

  2. 自动装配(autowiring):spring自动满足bean之间的依赖,也就是我们说的IoC/DI;

经验:

  • 组件扫描和自动装配组合发挥巨大威力,使得显示的配置降低到最少。

  • 推荐不使用自动装配xml配置 , 而使用注解


测试环境搭建 牛刀小试

1、新建一个maven项目

2、新建两个实体类,Cat Dog 都有一个叫的方法

//猫
public class Cat {
	public void cry() {
 		System.out.println("喵喵喵~");
	}
}
//狗
public class Dog {
	public void cry() {
 		System.out.println("汪汪汪~");
	}
}

3、新建一个用户类 User

public class User {
	private Cat cat;//猫
	private Dog dog;//狗狗
	private String masterName;//主人名称
}

4、编写Spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="dog" class="com.aiden.pojo.Dog"/>
<bean id="cat" class="com.aiden.pojo.Cat"/>

<bean id="user" class="com.aiden.pojo.User">
 	<property name="cat" ref="cat"/>
 	<property name="dog" ref="dog"/>
 	<property name="masterName" value="王小二"/>
</bean>
</beans>

5、测试

public class MyTest {
	@Test
	public void testMethodAutowire() {
 	ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
 	User user =  context.getBean("user",User.class);
 	user.getCat().cry();
 	user.getDog().cry();
	}
}

6、结果正常输出。


byName

autowire byName (按名称自动装配)

问题: 由于在手动配置xml过程中,常常发生字母缺漏和大小写等错误,而无法对其进行检查,使得开发效率降低。

分析: 采用自动装配将避免这些错误,并且使配置简单化。

测试:

​ 1、修改bean配置,增加一个属性 autowire=“byName”

​ 2、再次测试,结果依旧成功输出!

​ 3、我们将 cat 的 bean id 修改为 catXXX

​ 4、再次测试, 执行时报空指针java.lang.NullPointerException。因为按byName规则找不对应set方法,真正的setCat就没执行,对象就没有初始化,所以调用时就会报空指针错误。

小结:

当一个bean节点带有 autowire byName的属性时。

  1. 将查找其类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。
  2. 去spring容器中寻找是否有此字符串名称id的对象。
  3. 如果有,就取出注入;如果没有,就报空指针异常。

byType

autowire byType (按类型自动装配)

使用autowire="byType"首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。NoUniqueBeanDefinitionException

测试:

  1. 将user的bean配置修改一下 : autowire=“byType”

  2. 测试,正常输出

  3. 再注册一个cat 的bean对象!

    <bean id="dog" class="com.aiden.pojo.Dog"/>
    <bean id="cat" class="com.aiden.pojo.Cat"/>
    <bean id="catNew" class="com.aiden.pojo.Cat"/>
    
    <bean id="user" class="com.aiden.pojo.User" autowire="byType">
    	<property name="masterName" value="王小二"/>
    </bean>
    
  4. 测试,报错:NoUniqueBeanDefinitionException

  5. 删掉catNew,将cat的bean名称改掉!测试!因为是按类型装配,所以并不会报异常,也不影响最后的结果。甚至将id属性去掉,也不影响结果。

这就是按照类型自动装配!

使用注解

jdk1.5开始支持注解,spring2.5开始全面支持注解

5.2、Spring中Bean的自动装配3-1

什么是自动装配

<bean id="sysUserMapper" class="cn.cvs.mapper.SysUserMapperImpl"></bean>
<!--配置业务Bean并注入DAO实例-->
<bean id="userService" class="cn.cvs.service.SysUserServiceImpl">
	<property name="sysUserMapper" ref="sysUserMapper">
</bean>
  • Spring可以根据属性类型、名称等自动进行注入

如何使用自动装配

​ 设置<bean>元素的autowire属性

<bean id="userService" class="cn.cvs.service.SysUserServiceImpl" autowire="byName" />
5.3、Spring中Bean的自动装配3-2

Spring提供的4种自动装配类型

属性说明
no不使用自动装配。Bean的依赖关系必须通过property元素定义
byType根据属性类型自动装配
byName根据属性名自动装配
constructor与byType的方式类似,不同之处在它应用于构造器参数
5.4、Spring中Bean的自动装配3-3

问题

  • 如果需要配置的Bean很多,为每个Bean都配置autowire属性是不是也很繁琐?应该怎么处理?

分析

  • 可以通过<beans>标签的default-autowire属性设置全局自动装配功能
<?xml version="1.0" encoding="UTF-8"?>
<beans …… default-autowire="byName">
	<!--省略其他代码-->
</beans>
六、Spring中Bean的作用域
6.1、Spring中Bean的作用域
作用域说明
singleton默认值。以单例模式创建Bean的实例,即容器中该Bean的实例只会被创建一个
prototype每次从容器中获取Bean时,都会创建一个新的实例
request用于Web应用环境,针对每次HTTP请求都会创建一个实例
session用于Web应用环境,同一个会话共享同一个实例
global session仅在Portlet的Web应用中使用,同一个全局会话共享一个实例。对于非Portlet环境,等同于session

示例

<!--配置DAO-->
<bean id="sysUserMapper" class="cn.cvs.mapper.SysUserMapperImpl" autowire="byType" scope="singleton" />
6.2、使用注解指定Bean的作用域
  • 使用@Scope注解指定Bean的作用域
@Scope("prototype")
@Service
public class SysUserServiceImpl implements SysUserService {
	// 业务编码略
}
七、本章总结
7.1、本章总结

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

众生云海,一念初见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值