第3章 Spring中的Bean详解(2)

目录

1  Bean的装配方式

2  基于XML的装配

 2.1 传入参数的类型

 2.2 字面值注入(SpringDIConfig)

name属性:属性的名称,与Bean中setter方法的名称一致。

value属性:属性的值,指定的值是字面值。

标签:标签内的文本指定属性的值,类型为字面值类型。可使用null值,将属性的值设置为null。

 2.3 引用注入(SpringDIConfig)

 2.4 引用注入举例(SpringDIConfig)

 2.5 集合类型注入(XMLBasedAssembly)

2.6 复合类型注入(Spring配置依赖)

 2.7 基于XML装配的步骤

3  基于注解的装配

3.1 Spring中常用的注解

 3.2 基于Annotation的装配

3.3 包扫描的形式(SpringScan)

3.4 自动装配(autowire) 

 (1)autowire="byName"

(2)autowire="byType" 

(3)autowire="constructor" 

 3.5 自动装配的使用步骤

4  本讲小结


1  Bean的装配方式

什么是Bean的装配

        Bean的装配可以理解为依赖关系注入Bean的装配方式即Bean依赖注入的方式Spring容器支持多种形式的Bean的装配方式,如基于XML的装配、基于注解(Annotation)的装配和自动装配(其中最常用的是基于注解的装配),次课将主要讲解这三种装配方式的使用

基于XML的装配

 2.1 传入参数的类型

装配的本质:通过<constructor-arg>元素调用有参构造器,<property>元素调用setter方法,调用时传入参数的类型有:

基本类型及其包装类、 String Date 等类型(字面值类型)
<value> 子元素 value 属性 注入字面 ( 可用字符串表示的 ) 值;
对象类型:引用 IoC 容器中定义的其他 Bean
<bean> <constructor- arg > <ref> 子元素 ref 属性 注入;
List Set Map 等集合以及数组
数组: <array> 标签; List <list> 标签; Set <set> 标签
Map <map> 标签; Propertis <props> 标签

 2.2 字面值注入(SpringDIConfig)

name属性:属性名称Beansetter方法名称一致

value属性:属性,指定的值字面值

<value>标签标签内的文本指定属性的,类型为字面值类型。可使用null属性的值设置为null

<bean id="students" class="cn.com.sise.pojo.Students">
   <constructor-arg name="num" value="1640707000" />
      <property name="name">
           <value>黄霸天</value>
      </property>
   <constructor-arg name="major">
        <value>物联网工程</value>
   </constructor-arg>
</bean>
public class Student {
 
	public Student() {
		System.out.println("OK");
	}
	public Student(int age) {
		System.out.println("age="+age);
	}
	public Student(String name) {
		System.out.println("name="+name);
	}
	public Student(int age,String name) {
		System.out.println("age="+age+",name="+name);
	}
	public Student(Date now) {
		System.out.println("现在的时间是:"+now);
	}
	public Student(List<Object> list) {
		for (Object object : list) {
			System.out.println(object);
		}
	}
	public Student(Object [] array) {
		for (Object object : array) {
			System.out.println(object);
		}
	}
	public Student(Set<Object> set) {
		for(Object object : set) {
			System.out.println(object);
		}
	}
	public Student(Map<String,Object> map) {
		Set<String> keys = map.keySet();
		for (String key : keys) {
			System.out.println(key+":"+map.get(key));
		}
	}
	public Student(Properties properties) {
		System.out.println(properties.get("driver"));
		System.out.println(properties.get("userName"));
		System.out.println(properties.get("password"));
		System.out.println(properties.get("url"));
	}
}

 第一种方法,按顺序排列

<bean class="Student">
	<!-- 这里我们直接使用标签属性value,直接给构造函数参数列表赋值,
写了两个constructor-arg标签,则就是对应有两个参数的构造函数,
想要赋的值 按参数列表的顺序写就可以了 -->
	<constructor-arg value="12"></constructor-arg>
	<constructor-arg value="张三"></constructor-arg>
</bean>

 第二种方法,使用name标签属性

<bean class="Student">
	<!-- 这里的name标签属性对应的就是参数列表中的参数名,不按顺序写他也会自动比对的 -->
	<constructor-arg name="name" value="张三"></constructor-arg>
	<constructor-arg name="age" value="12"></constructor-arg>
</bean>

 第三种方法,使用index标签属性

<bean class="Student">
	<!-- index为参数列表中参数的顺序,从0开始 -->
	<constructor-arg index="1" value="张三"></constructor-arg>
	<constructor-arg index="0" value="12"></constructor-arg>
</bean>

 第四种方法,使用type标签属性

<bean class="Student">
	<!-- 这里int不可以是java.lang.Integer,要和参数数据类型严格一致 -->
	<constructor-arg type="int" value="12"></constructor-arg>
	<constructor-arg type="java.lang.String" value="张三"></constructor-arg>
</bean>

 2.3 引用注入(SpringDIConfig)

<ref> 定属性的值, 类型为 引用对象类型 可通过以下属性 引用 其他 Bean
p arent 属性: 引用 父容器 中定义的 Bean
bean 属性 引用全局 中的 bean 可以 引用同一配置文件中 或者 父容器中的 Bean 可以是不同 XML 文件中的 Bean 实例。
ref 属性 属性 的值 ,其值 引用对象 类型,即其他 Bean id
与设值注入的比较:
ref 引用一个 已经存在的对象 value 创建一个 新的对象
value 一些简单类型的值, ref 可引用 其他的 bean 对象

 2.4 引用注入举例(SpringDIConfig)

<bean id="birthDay" class="cn.com.sise.pojo.BirthDay"/>
<bean id="school" class="cn.com.sise.pojo.School">
    <constructor-arg name="students" ref="students">
    </constructor-arg>
    <constructor-arg name="teachers">
        <ref bean="teachers"></ref>
    </constructor-arg>
</bean>
<property name="birth" ref="birthDay" />
<constructor-arg>标签的属性如上图:
index属性:指定参数是第几个,值从0开始
type属性:指定参数类型,决定使用哪个构造函数
<constructor-arg index="0" type="java.lang.String"    value="AA" />

 2.5 集合类型注入(XMLBasedAssembly)

<List> 声明该依赖对象为一个 list 集合,其下 用以下标签:
<value> 指定 list 集合中的字面 ( 基本类型、字符串类型等 )
<ref > 指定 list 集合中的 引用值 ,为其他的对象 Bean
list 列表 可以包含 多个内部 bean ref collection value 元素
列表 也可以映射到数组 类型 ,必要 的转换是 自动执行
<bean id="order" class="com.qst.chapter07.config.Order">
     <property name="myList">
        <list>
           <value>1234</value>
           <ref bean="orderItem1" />
        </list>
    </property>
</bean>

 <set>声明该依赖对象为一个set集合,用法list标签相同

set集合可包含多个内部beanrefcollectionvalue元素

     <property name="myList">
        <set>
            <value>1234</value> <ref bean="orderItem1" />
        </set>
    </property>
</bean>

 list标签和set标签中的属性:

value-type属性指定值的类型,

merge="default"使用父/bean时,启用合并

 

 

 <map>:声明该依赖对象为一个map集合,其下<entry>

<entry>:声明map集合下的一个键值对,其属性如图所示,其子标签如下图:

key属性:键值对中的,一般为字符串

<value>:键值对中的,类型为字面值

<ref>:键值对中的值,引用其他的Bea

<property name="someMap">
 <map key-type="java.lang.String" value-type=“java.util.Date">
        <entry value="some1" key="key1"></entry>
        <entry value-ref="some2" key="key2"></entry>
        <entry value-ref="some3" key="key3"></entry>
   </map>
</property>

 <props>:声明该依赖对象为一个properties集合,其下:

<prop>:用于设置集合中的一个键值对

key属性:指明键值对中的键,一般为字符串

文本内容指明键值对中的值,一般为字符串

属性元素与map元素的区别:值必须是字符串,可能为空 

<bean id="order" class="com.qst.chapter07.config.Order">
  <property name="myProp">
    <props>
      <prop key="aaa">AAA</prop>
      <prop key="bbb">BBBBB</prop>
    </props>
   </property>
</bean>

 命名空间注入(用的不多)

对于设置注入与构造注入,在配置文件中,还可使用命名空间注入让注入的值以<bean/>标签的属性的方式出现。

根据注入实现方式,分为P命名空间注入C命名空间注入

p命名空间注入采用设值注入方式

c命名空间注入采用构造注入方式

注入的Bean对象的属性类型:

基本类型:p:属性名="属性值"

引用类型:ref属性  p:属性名-ref="其他Bean的id"

2.6 复合类型注入(Spring配置依赖)

xmlns:p="http://www.springframework.org/schema/p" 
xmlns:c="http://www.springframework.org/schema/c"
<!-- 使用p命名空间,通过通过set方法注入bean定义-->
<bean id="stu2" class="cn.com.sise.Student"  
           p:sNo="002" p:sName="Tom"
          p:age="22" p:banji-ref="banji">
</bean>
<!-- 使用c命名空间,通过构造方法注入的bean定义-->
<bean id="stu3" class="cn.com.sise.Student" 
          c:_0=“003” c:_1=“Jerry "  //c:_0表示第一个参数
          c:_2="22" c:_3-ref="banji">
</bean>
c:_n=“参数值”中的n表示注入的是第几个参数(从0开始)

 util命名空间:可以快速的定义listmapset等。

首先需要在XML配置文件中引入其对应的util命名空间,见图 

 这部分内容,大家感兴趣的自己看看Spring| Spring之util命名空间_YvesHe的博客-CSDN博客_spring util

嵌套Bean传入值
将<bean.../>配置在 <property.../> <constructor-arg.../> 中,只是作为setter方法、或者构造器的参数。

Spring容器不能直接获取该Bean因此嵌套Bean不需要id

<!-- 使用嵌套Bean -->
<bean id="stu4" class="cn.com.sise.Student" 
       p:sNo="004" p:sName="Tom"  p:age="22">
    <property name="banji">
       <bean class="cn.com.sise.BanJi" 
            p:cNo="2" p:cName="Web2"></bean>
   </property>
</bean>

 2.7 基于XML装配的步骤

创建Java类,提供有参、无参构造及属性setter方法;

public User(String username, Integer password, List<String> list) {
   super();
    this.username = username;
    this.password = password;
    this.list = list;
} 
public User() { super();}
//省略属性setter方法

创建Spring配置文件beans5.xml,用2种方式配置Bean

<bean id="user1" class="com.itheima.assemble.User">
     <constructor-arg index="0" value="tom" />
        ...
</bean>
<bean id="user2" class="com.itheima.assemble.User">
     <property name=“username” value=“张三”  />
        ...
</bean>

创建测试类,测试程序。

public class XmlBeanAssembleTest {
   public static void main(String[] args) {
     String xmlPath = "com/itheima/assemble/beans5.xml";
     ApplicationContext applicationContext = 
       new ClassPathXmlApplicationContext(xmlPath);
      System.out.println(applicationContext.getBean("user1"));
      System.out.println(applicationContext.getBean("user2"));
      }
}

基于注解的装配

3.1 Spring中常用的注解

@Component

描述Spring中的Bean,它是一个泛化的概念,仅仅表示一个组件

@Repository

数据访问层(DAO)的类标识为Bean

@Service

业务层(Service)的类标识为Spring中的Bean

@Controller

控制层(Controller)的类标识为Bean

@Autowired

Bean属性、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean自动装配,默认是byType的自动装配。

@Qualifier

byName自动装配,指定注入Bean的名称,对Bean的成员变量、方法入参、构造函数入参进行标注,常与@Qualifier 结合使用。

@Inject

与上两个注释用法相同,由JSR-330提供。

@Resource

功能同@Autowired,有两个重要属性:nametype。分别解析为Bean实例的名称类型

@Bean

告诉方法,产生一个Bean对象,并交给Spring管理。

@ComponentScan

默认会扫描该配置类所在的包下所有的配置类,相当于<context:component-scan>

@PostConstruct

修饰方法,相当于init-method属性

@PreDestroy

修饰方法,相当于destroy-method属性

@Lazy

指定延迟初始化。相当于lazy-init属性

@Value

属性注入值(属性上)

@Scope

指定Bean的作用域相当于scope属性

@DependsOn

强制初始化其他Bean,对应depends-on属性。

 3.2 基于Annotation的装配

创建接口UserDao并定义方法;

创建接口实现类UserDaoImpl,用@Repository声明类;

@Repository("userDao") 
public class UserDaoImpl implements UserDao{
   public void save(){
       System.out.println("userdao...save...");
   }
}

创建接口UserService,并定义方法;

创建接口实现类UserServiceImpl,用@Service声明类,并使用@Resource注入UserDao属性;

   @Service("userService") 
   public class UserServiceImpl implements UserService{
 	@Resource(name="userDao") 
 	private UserDao userDao;
 	public void save() {
		this.userDao.save();		
	}
  }

创建控制器类,用@Controller声明,并使用@Resource注入UserService属性;

@Controller("userController")
    public class UserController {
 	@Resource(name="userService")
 	private UserService userService;
 	public void save(){
 		this.userService.save();
 	}
    }

创建Spring配置文件,配置Bean

<context:annotation-config />
<bean id="userDao" class="com.itheima.annotation.UserDaoImpl"/>
<bean id="userService" class="com.itheima.annotation.UserServiceImpl"/>
<bean id="userController" class="com.itheima.annotation.UserController"/>

创建测试类,测试程序。

public class AnnotationAssembleTest {
public static void main(String[] args) {
String xmlPath="com/itheima/annotation/beans6.xml";
   ApplicationContext applicationContext= 			       
     new ClassPathXmlApplicationContext(xmlPath);
    UserController userController= (UserController) applicationContext.getBean("userController");
 	userController.save();
          }
    } 

小提示: 除了可以像示例中通过<bean>元素来配置Bean外,还可以通过包扫描的形式来配置一个包下的所有Bean

<context:component-scan base-package="com.itheima.annotation" />

3.3 包扫描的形式(SpringScan)

上述案例除了可以通过<bean>元素来配置Bean外,还可以通过包扫描的形式来配置一个包下的所有Bean

<context:component-scan base-package="com.itheima.annotation"/>

其使用步骤如下:

1、在xml配置文件中,引入context命名空间,并添加<context:component-scan base-package="需要扫描的包(含子包) " >标签。扫描元素时,不需要在XML中提供任何bean配置元数据。

3、标注组件:为需要被扫描的类添加相应的注解。

4、测试:测试相应的组件是否被纳入Spring容器(是否被扫描)

//如果输出不为空,则测试类已被扫描并且纳入了Spring容器

修改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">
<context:component-scan 
base-package="cn.com.sise.service,cn.com.sise.action"/>
</beans>

3.4 自动装配(autowire) 

将一个Bean自动的注入到到其他BeanProperty中。 Spring<bean>中包含一个autowire属性,通过设置autowire的属性值来自动装配Beanautowire属性有5个值,其值如下表所示

 (1)autowire="byName"

当一<bean>带有autowire="byName"属性时:

<bean autowire="byName" id="school" class="com.sise.School"/>

①查找Bean所有的set方法名(或属性名),如setStudents获得将set去掉并且首字母小写的字符串,student

public class School {

 private Students students;

 private Teachers teachers;

public void setStudents(Students students) {

          this.students = students;}

public void setTeachers(Teachers teachers) {

          this.teachers = teachers;}}
②去 spring 容器中寻找是否有此字符串名称的 id 对象。

<bean id="students" class="com.sise.Students"/>

<bean id="teachers" class="com.sise.Teachers"/>

③如果有,就取出注入;如果没有,就报空指针异常。

(2)autowire="byType" 

<bean autowire="byType" id="school" class="com.sise.School"/>

①查找 Bean 类中所有 属性的类型 ,例如 属性 cat 的类型 Cat
public class School {

 private Students students;

 private Teachers teachers;

public void setStudents(Students students) {

          this.students = students;}

public void setTeachers(Teachers teachers) {

          this.teachers = teachers;}}
②去 spring 容器中寻找是否有此字符串名称 class 属性

<bean id="students" class="com.sise.Students"/>

<bean id="teachers" class="com.sise.Teachers"/>

③如果有,就取出注入;如果没有,就报空指针异常

(3)autowire="constructor" 

constructor :使用构造方法完成对象注入,也是 根据构造方法的参数类型 进行对象查找,相当于采用 byType 的方式。
Ø 测试此方式时,在实体类中 要有参数 类型的构造 方法
Ø 具有 byType 自动装配相同的 局限性
Ø 发现 多个 Bean 匹配 某个构造器 的参数时 Spring 不会尝试猜测哪一个 Bean 更适合自动 装配,会 装配失败
Ø 如果 一个类有多个构造器,它们都满足自动装配的条件时, Spring 也不会尝试猜测哪一个构造器更适合 使用。

<bean autowire="constructor" id="school" class="com.sise.School"/>

<bean id="students" class="com.sise.Students"/>

<bean id="teachers" class="com.sise.Teachers"/>

 3.5 自动装配的使用步骤

自动装配,使用方式如下:

修改上一节UserServiceImpleUserController,分别增加类属性的setter方法;

修改Spring配置文件,使用autowire属性配置Bean

重新测试程序。

<bean id="userDao" class="com.itheima.annotation.UserDaoImpl"/>
<bean id="userService" class="com.itheima.annotation.UserServiceImpl" autowire="byName"/>
<bean id="userController" class="com.itheima.annotation.UserController" autowire="byName"/>

本讲小结

SpringBeanBean的三种装配方式进行了详细的讲解,首先讲解了Bean装配的概念,接下来介绍了基于XML的装配和基于注解的装配,最后以案例介绍了不同方式的Bean的装配的步骤

       

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Pig Pig Cat

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

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

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

打赏作者

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

抵扣说明:

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

余额充值