跟着刚哥学习Spring框架--通过XML方式配置Bean(三)

Spring配置Bean有两种形式(XML和注解)

今天我们学习通过XML方式配置Bean

1、 Bean的配置方式

  通过全类名(反射)的方式

    

    √ id:标识容器中的bean。id唯一。

    √ class:bean的全类名,通过反射的方式在IOC容器中创建Bean,所以要求Bean中必须有无参的构造器

2、依赖注入的方式

  1)属性注入:通过setter方法注入Bean的属性值或依赖的对象

  

  属性注入使用<Property>元素,使用name指定Bean的属性名称,使用value指定Bean的属性的值

  2)构造器注册:通过构造方法注入Bean的属性和值

  首先创建一个Car类

 1 public class Car {
 2     private String brand;
 3     private int speed;
 4     private String color;
 5     public Car(String brand, int speed, String color) {
 6         this.brand = brand;
 7         this.speed = speed;
 8         this.color = color;
 9     }
10     @Override
11     public String toString() {
12         return "Car [brand=" + brand + ", speed=" + speed + ", color=" + color + "]";
13     }
14
15 }

  然后加入配置文件配置节点

1 <bean id="car" class="com.hzg.spring.beans.Car">
2     <constructor-arg value="Audi"></constructor-arg>
3     <constructor-arg value="120"></constructor-arg>
4     <constructor-arg value="black"></constructor-arg>
5 </bean>

  Main方法开启Spring容器并使用

1 // 1.创建Spring 的IOC的容器对象
2 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
3
4 // 2.从IOC容器中获取bean实例
5 Car car = (Car)ctx.getBean(Car.class);
6
7// 3、调用hello方法
8 System.out.println(car);

  输出结果:Car [brand=Audi, speed=120, color=black]

  如果想指定给属性的顺序赋值,可以使用index属性

1 <bean id="car" class="com.hzg.spring.beans.Car">
2     <constructor-arg value="Audi" index="0"></constructor-arg>
3     <constructor-arg value="120" index="1"></constructor-arg>
4     <constructor-arg value="black" index="2"></constructor-arg>
5 </bean>

  如果想指定给属性的顺序赋值,也可以使用type属性

1 <bean id="car" class="com.hzg.spring.beans.Car">
2     <constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
3     <constructor-arg value="120" type="int"></constructor-arg>
4     <constructor-arg value="black" type="java.lang.String"></constructor-arg>
5 </bean>

  3)工厂方法注入

    此方式基本不用

3、引用其他Bean

  1)引用外部Bean

 1 <bean id="car" class="com.hzg.spring.beans.Car">
 2     <constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
 3     <constructor-arg value="120" type="int"></constructor-arg>
 4     <constructor-arg value="black" type="java.lang.String"></constructor-arg>
 5 </bean>
 6
 7 <bean id="person" class="com.hzg.spring.beans.Person">
 8     <property name="name" value="hzg"></property>
 9     <property name="age" value="32"></property>
10     <!-- 使用 property的ref属性建立Bean之间的引用关系-->
11     <property name="car" ref="car"></property>
12 </bean>
  使用 property的ref属性建立Bean之间的引用关系

  2)引用内部Bean

 1 <bean id="person" class="com.hzg.spring.beans.Person">
 2     <property name="name" value="hzg"></property>
 3     <property name="age" value="32"></property>
 4     <!-- 内部Bean,不能被外部引用,只能在内部使用-->
 5     <property name="car">
 6         <bean class="com.hzg.spring.beans.Car">
 7             <constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
 8             <constructor-arg value="120" type="int"></constructor-arg>
 9             <constructor-arg value="black" type="java.lang.String"></constructor-arg>
10         </bean>
11     </property>
12 </bean>

  因为id是为了让外部引用,而内部Bean内部只用一次,不能被外部引用,随意不写id。

4、级联属性

1 <bean id="person" class="com.hzg.spring.beans.Person">
2     <property name="name" value="hzg"></property>
3     <property name="age" value="32"></property>
4     <property name="car" ref="car"></property>
5     <!-- 级联属性赋值 -->
6     <property name="car.price" value="30000"></property>
7 </bean>

  注意:属性想用car.price的级联,首先car必须要先初始化,否则会有异常

4、集合属性

当我们的Bean中有集合元素的时候,Spring中可以通过一组内置的xml标签(<list>、<set>、<map>)来配置集合属性。

  1)List集合:

   刚才的Person类有一个car属性,现在我们修改一下,Person类中有一个List<car>,即一个人拥有多辆车。

 1 public class Person {
 2     private String name;
 3     private int age;
 4     private List<Car> cars;
 5
 6     //为上面的3个属性设置getter和setter方法
 7     public String getName() {
 8         return name;
 9     }
10     public void setName(String name) {
11         this.name = name;
12     }
13     public int getAge() {
14         return age;
15     }
16     public void setAge(int age) {
17         this.age = age;
18     }
19     public List<Car> getCars() {
20         return cars;
21     }
22     public void setCars(List<Car> cars) {
23         this.cars = cars;
24     }
25 }

  配置文件修改如下:

 1 <bean id="car1" class="com.hzg.spring.beans.Car">
 2     <constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
 3     <constructor-arg value="120" type="int"></constructor-arg>
 4     <constructor-arg value="black" type="java.lang.String"></constructor-arg>
 5 </bean>
 6 <bean id="car2" class="com.hzg.spring.beans.Car">
 7     <constructor-arg value="Ford" type="java.lang.String"></constructor-arg>
 8     <constructor-arg value="100" type="int"></constructor-arg>
 9     <constructor-arg value="black" type="java.lang.String"></constructor-arg>
10 </bean>
11 <bean id="car3" class="com.hzg.spring.beans.Car">
12     <constructor-arg value="Toyota" type="java.lang.String"></constructor-arg>
13     <constructor-arg value="95" type="int"></constructor-arg>
14     <constructor-arg value="black" type="java.lang.String"></constructor-arg>
15 </bean>
16 <bean id="person" class="com.hzg.spring.beans.Person">
17     <property name="name" value="hzg"></property>
18     <property name="age" value="32"></property>
19     <!-- 集合属性(List),使用ref来配置子节点信息 -->
20     <property name="cars">
21         <list>
22             <ref bean="car1"></ref>
23             <ref bean="car2"></ref>
24             <ref bean="car3"></ref>
25         </list>
26     </property>
27 </bean>

   2)Map集合:

   如果是<map>集合的话,只需要把list换成map即可。

1 <!-- 集合属性(Map),使用entry来配置map的子节点信息 -->
2 <property name="cars">
3   <map>
4    <entry key="A" value-ref="car1" ></entry>
5    <entry key="B" value-ref="car2" ></entry>
6    </map>
7 </property>

 3) 现在这么多集合Bean能不能抽出来,以供多个Bean进行引用,那么就需要使用util

 1 <bean id="person" class="com.hzg.spring.beans.Person">
 2     <property name="name" value="hzg"></property>
 3     <property name="age" value="32"></property>
 4     <!-- 引用util -->
 5     <property name="cars" ref="cars"></property>
 6 </bean>
 7 <util:list id="cars">
 8     <ref bean="car1"></ref>
 9     <ref bean="car2"></ref>
10 </util:list>

 4)使用p命名空间 

  Sping从2.5版本开始引入一个新的P的命名空间,通过使用P命名空间后,使得Xml的配置方式进一步简化

1 <!-- 通过P命名空间为Bean属性赋值,相对于传统的配置方式更加简洁 -->
2 <bean id="person" class="com.hzg.spring.beans.Person" p:name="hzg" p:age="32" p:cars-ref="cars">
3 </bean>

 5、使用autowire属性进行Bean的自动装配

 当我们要往一个bean的某个属性里注入另外一个bean,我们会使用<property ref=“”>标签的形式。但是对于大型项目这种方式其实是不可取的。

1 <!--
2      大型项目中我们一般使用autowire属性自动装备Bean,autowire属性有两个值:byName和byType
3         byName:根据Bean的名字和当前的Bean的setter属性名称进行装配
4         byType:根据Bean的类型进行装配,若有1个以上的类型,则抛异常
5 -->
6 <bean id="person" class="com.hzg.spring.beans.Person" autowire="byType">
7      <property name="name" value="hzg"></property>
8      <property name="age" value="32"></property>
9 </bean>

  自动装配的特点:

   1)只有引用类型才可以自动装配。

   2)autowire属性是在bean的级别上,一旦指定,当前bean的所有引用类型都必须使用自动装配。

     3)byType和byName的只能选择其一。

6、配置上的继承(parent属性)

  当我们有两个或者以上的同一个类型的Bean做实例化的时候,我们可以将一些公共的提成通用Bean。这样其他的Bean继承它即可以了。

1 <bean id="address1" class="com.hzg.Address" p:provice="Hebei" p:city="LangFang" p:street="YingBing">
2
3 </bean>
4 <bean id="address2" class="com.hzg.Address" p:provice="Hebei" p:city="LangFang" p:street="YanLing">
5
6 </bean>
7 <bean id="address3" class="com.hzg.Address" p:provice="Hebei" p:city="LangFang" p:street="YanShun">
8
9 </bean>

  以上Bean中用的都是address这个类,都是省市街道的赋值,只是在街道上每个不一样,所以我们完全可以把通用的提出来。

1 <bean id="address" class="com.hzg.Address" p:provice="Hebei" p:city="LangFang" p:street="YingBing">
2
3 </bean>
4 <bean id="address1" parent="address" p:street="YanLing">
5
6 </bean>
7 <bean id="address2" parent="address" p:street="YanShun">
8
9 </bean>

7、Bean的作用域(scope属性)

<bean id="address" class="com.hzg.Address" p:provice="Hebei" p:city="LangFang" p:street="YanShun">

</bean>
1 ApplicationContext ctx = new ClassPathXmlApplicationContext("configspring.xml");
2 Address address1 = (Address) ctx.getBean("address");
3 Address address2 = (Address) ctx.getBean("address");
4 System.out.println(address1==address2);

  输出结果为:true

  说明默认为单例模式的,它只要是看scope属性的。

  使用Bean的scope属性来配置Bean的作用域的,scope有两个重要的属性值。

    singleton默认值,容器初始化时创建Bean实例,在整个容器的生命周期内只创建一个Bean,单例的。

    prototype:原型的,容器初始化时不创建Bean的实例,而在每次请求时都创建一个新的Bean的实例,并返回。

8、使用外部属性文件(property-placeholder 属性占位符)

  新建一个db.properties文件

1 user=root
2 password=123456
3 driverClass=com.mysql.jdbc
4 jdbcUrl=jdbc:mysql:///test

  配置上属性占位符文件的地址,并在使用的过程中使用${}的格式取值

1 <!-- 导入属性文件 -->
2 <context:property-placeholder location="db.properties"></context:property-placeholder>
3 <bean id="dataSource" class="com.hzg.MyDataSource">
4   <!-- 使用外部属性文件的属性值 -->
5   <property name="user" value="${user}"></property>
6   <property name="password" value="${password}"></property>
7    <property name="diverClass" value="${driverClass}"></property>
8    <property name="jdbcUrl" value="${jdbcUrl}"></property>
9 </bean>

  MyDataSource文件:

 1 public class MyDataSource {
 2     private String user;
 3     private String password;
 4     private String diverClass;
 5     private String jdbcUrl;
 6
 7     public String getUser() {
 8         return user;
 9     }
10
11     public void setUser(String user) {
12         this.user = user;
13     }
14
15     public String getPassword() {
16         return password;
17     }
18
19     public void setPassword(String password) {
20         this.password = password;
21     }
22
23     public String getDiverClass() {
24         return diverClass;
25     }
26
27     public void setDiverClass(String diverClass) {
28         this.diverClass = diverClass;
29     }
30
31     public String getJdbcUrl() {
32         return jdbcUrl;
33     }
34
35     public void setJdbcUrl(String jdbcUrl) {
36         this.jdbcUrl = jdbcUrl;
37     }
38
39     @Override
40     public String toString() {
41         return "MyDataSource{" +
42                 "user=‘" + user + ‘\‘‘ +
43                 ", password=‘" + password + ‘\‘‘ +
44                 ", diverClass=‘" + diverClass + ‘\‘‘ +
45                 ", jdbcUrl=‘" + jdbcUrl + ‘\‘‘ +
46                 ‘}‘;
47     }
48 }

  Main方法:

1 ApplicationContext ctx = new ClassPathXmlApplicationContext("configspring.xml");
2 MyDataSource myDataSource = (MyDataSource) ctx.getBean("dataSource");
3 System.out.println(myDataSource);

  输出结果:MyDataSource{user=‘root‘, password=‘123456‘, diverClass=‘com.mysql.jdbc‘, jdbcUrl=‘jdbc:mysql:///test‘}

9、Spring表达式SPEL表达式

 1 <bean id="person" class="com.hzg.Person">
 2  <!-- 使用SpEL 来应用其他的Bean -->
 3  <property name="car" value="#{car}"></property>
 4  <!-- 使用SpEL 来应用其他的Bean的属性 -->
 5  <property name="city" value="#{address.city}"></property>
 6  <!-- 使用SpEL 中使用运算符 -->
 7  <property name="info" value="#{car.price > 30000 ? ‘金领‘ : ‘白领‘}"></property>
 8  <!-- 使用SpEL 引用类的静态属性 -->
 9  <property name="yaowei" value="#{T(java.lang.Math).PI * 80}"></property>
10 </bean>

10、Spring中Bean的生命周期

  1)创建Bean的实例

  2)为Bean的属性设置值和对其他Bean的引用

  3)Bean后置处理器postProcessBeforeInitialization方法

  4)调用Bean的初始化方法(init-method)

  5)Bean后置处理器的postProcessAfterInitialization方法

  6)Bean正常使用

  7)当容器关闭时,调用Bean的销毁方法(destroy-method)

 实例:

 1 public class Car {
 2     public Car() {
 3         System.out.println("构造器……");
 4     }
 5     private String brand;
 6
 7     public void setBrand(String brand) {
 8         System.out.println("设置属性……");
 9         this.brand = brand;
10     }
11     public void init(){
12         System.out.println("初始化……");
13     }
14     public void destroy(){
15         System.out.println("销毁……");
16     }
17 }

  MyBeanProcessor必须实现BeanPostProcessor接口的两个方法

 1 public class MyBeanProcessor implements BeanPostProcessor {
 2     @Override
 3     public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
 4         System.out.println("postProcessBeforeInitialization……");
 5         return o;
 6     }
 7
 8     @Override
 9     public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
10         System.out.println("postProcessAfterInitialization……");
11         return o;
12     }
13 }

  配置文件

1 <bean id="car" class="com.hzg.Car" p:brand="Audi" init-method="init" destroy-method="destroy"></bean>
2 <!-- 配置Bean的后置处理器 -->
3 <bean class="com.hzg.MyBeanProcessor"></bean>

  Main方法

1 public static void main(String[] args) {
2  //由于ApplicationContext没有close方法,所以要使用它下面接口ConfigurableApplicationContext
3  ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("configspring.xml");
4  Car car = (Car) ctx.getBean("car");
5  System.out.println("使用Bean:" + car.toString());
6  //关闭IOC容器
7  ctx.close();
8 }

  输出结果:

postProcessBeforeInitialization……
postProcessAfterInitialization……
构造器……
设置属性……
postProcessBeforeInitialization……
初始化……
postProcessAfterInitialization……
使用Bean:[email protected]
销毁……

-------------------------------------------------------------------------------------------------------------------------

跟着刚哥学习Spring框架系列:

跟着刚哥学习Spring框架--创建HelloWorld项目(一)

跟着刚哥学习Spring框架--Spring容器(二)

跟着刚哥学习Spring框架--通过XML方式配置Bean(三)

跟着刚哥学习Spring框架--通过注解方式配置Bean(四)

跟着刚哥学习Spring框架--AOP(五)

  

时间: 2024-10-03 10:29:36

跟着刚哥学习Spring框架--通过XML方式配置Bean(三)的相关文章

跟着刚哥学习Spring框架--通过注解方式配置Bean(四)

组件扫描:Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件. 特定组件包括: 1.@Component:基本注解,识别一个受Spring管理的组件 2.@Respository:标识持久层组件 3.@Service:标识业务层组件 4.@Controller:标识表现层组件 Spring 有默认的命名策略: 使用非限定类名, 第一个字母小写. 也可以在注解中通过 value 属性值标识组件的名称 当在组件类上使用了特定的注解之后, 还需要在 Spring 的配置文件

跟着刚哥学习Spring框架--AOP(五)

AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入封装.继承.多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合.不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能.日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性.异常处理和透明的持续性也都是如此,这种散布在各

跟着刚哥学习Spring框架--Spring容器(二)

Spring容器 启动Spring容器(实例化容器) -- IOC容器读取Bean配置创建Bean实例之前,必须对它进行实例化(加载启动),这样才可以从容器中获取Bean的实例并使用.  Bean是Spring管理的基本单位,任何的Java对象和组件都被当成Bean处理,容器还负责管理Bean与Bean之间的依赖关系.  两种类型的启动实现   1.BeanFactory:IOC容器的基本实现,是Spring框架的基础设施,面向Spring本身: -- Spring容器最基本的接口就是BeanF

跟着刚哥学习Spring框架--创建HelloWorld项目(一)

1.Spring框架简介 Spring是一个开源框架,Spring是在2003年兴起的一个轻量级的开源框架,由Rod johnson创建.主要对JavaBean的生命周期进行管理的轻量级框架,Spring给JavaEE带来了春天. 2.Spring框架特点 √ 轻量级:不是说他的文件大小很小,指的Spring是非侵入性. 知识点:轻量级框架和重量级框架的区别 轻量级和重量级的框架是以启动程序所需要的资源所决定,比如EJB在启动程序的时候需要消耗大量的资源,内存和CPU,所以是重量级.√ 依赖注入

跟着刚哥学习Spring框架--JDBC(六)

Spring的JDBC框架 Spring JDBC提供了一套JDBC抽象框架,用于简化JDBC开发. Spring主要提供JDBC模板方式.关系数据库对象化方式.SimpleJdbc方式.事务管理来简化JDBC编程 Spring提供了3个模板类: JdbcTemplate:Spring里最基本的JDBC模板,利用JDBC和简单的索引参数查询提供对数据库的简单访问. NamedParameterJdbcTemplate:能够在执行查询时把值绑定到SQL里的命名参数,而不是使用索引参数. Simpl

【常用配置】Spring框架web.xml通用配置

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="Web

学习Spring框架等技术的方向、方法和动机

学习Spring框架最早学习Spring框架是在大二的时候,当时看了几本书,看了一些视频,主要是传智播客的.更多的,还是写代码,单独写Spring的,也有与Struts和Hibernate等框架整合的.很久以来,主要使用了Spring的注入功能和事务管理,其它功能没怎么用到,可能是没有这方面的需求吧.有好几次都想对Spring有个深入的学习,比如把Spring中的全部功能都了解下,学习下Spring的原理.这2件事情,都是半途而废,有一定深入或全面学习,没有坚持下去. 广度与深度回顾下自己学习技

Spring学习(五)bean装配详解之 【XML方式配置】

本文借鉴:Spring学习(特此感谢!) 一.配置Bean的方式及选择 配置方式 在 XML 文件中显式配置 在 Java 的接口和类中实现配置 隐式 Bean 的发现机制和自动装配原则 方式选择的原则 最优先:通过隐式 Bean 的发现机制和自动装配的原则. 基于约定优于配置的原则,这种方式应该是最优先的 好处:减少程序开发者的决定权,简单又不失灵活. 其次:Java 接口和类中配置实现配置 在没有办法使用自动装配原则的情况下应该优先考虑此类方法 好处:避免 XML 配置的泛滥,也更为容易.

spring 注解方式配置Bean

概要: 再classpath中扫描组件 组件扫描(component scanning):Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件 特定组件包括: @Component:基本注解,标示了一个受Spring管理的组件(可以混用,spring还无法识别具体是哪一层) @Respository:建议标识持久层组件(可以混用,spring还无法识别具体是哪一层) @Service:建议标识服务层(业务层)组件(可以混用,spring还无法识别具体是哪一层) @Con