java教程 spring基于xml配置

spring容器

  • 1、在springIOC 容器读取 Bean 配置,创建 Bean 实例之前,需要先对spring 容器进行实例化。只有在容器实例化之后,才可以 IOC 容器中获取 Bean 实例,并且使用。
  • 2、spring提供了两种类型的springIOC容器实现。
    • BeanFactory: IOC容器的底层实现。
    • ApplicationContext: 提供了更多得高级特性,是BeanFactory的子接口。
    • BeanFactory是Spring框架的基础设施,面向spring本身。ApplicationContext面向使用Spring框架的开发者,几乎所有的应用场合都是使用ApplicationContext,而不是BeanFactory.
    • 无论使用何种方式,配置文件都相同。
  • 3、spring容器接口ApplicationContext
    • ConfigurableApplicationContext 扩展于 ApplicationContext, 新增两个主要方法:refresh(),close(),让ApplicationContext具有启动,刷新和关闭上下文的能力。
    • ClassPathXmlApplicationContext: 实现 ConfigurableApplicationContext接口,从类路径下加载配置文件。
    • FileSystemXmlApplicationContext:实现 ConfigurableApplicationContext接口,从文件系统中加载配置文件。
    • ApplicationContext 在初始化上下文时就实例化所有单例的Bean。
    • WebApplicationContext 是专门为Web应用而准备的,它允许从相对于WEB根目录的路径中完成初始化工作。
# 1.创建iOC容器,并且读取配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

# 2.从容器中获取bean
HelloWorld helloWorld = (HelloWorld) applicationContext.getBean("helloworld");

# 3.获取bean的属性
helloWorld.hello();

关于xml中的文件头

  • xmlns : 表示默认的命名空间,对于默认的namespace中的元素,可以不使用前缀。
  • xmlns:xsi : 表示使用xsi作为前缀的命名空间,前缀xsi需要在文档中声明。
  • xsi:schemaLocation : 表示是namespace为xxx的schemaLocation属性。它定义了xml Namespace和对应的XSD(xml schema Defination)文档的位置的关系。由多个URI组成,由空格或者换行分隔。第一个URI是定义xml Namespace的值,第二个URI给出schema文档的位置,schema处理器将从这个位置读取schema文档,该文档的targetNamespace必须与第一个URI相匹配。
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xmlns:aop="http://www.springframework.org/schema/aop"
  xmlns:tx="http://www.springframework.org/schema/tx" 
 xmlns:context="http://www.springframework.org/schema/context"
  xmlns:mvc="http://www.springframework.org/schema/mvc" 
 xmlns:task="http://www.springframework.org/schema/task"
 
  xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
        http://www.springframework.org/schema/task
        http://www.springframework.org/schema/task/spring-task-3.1.xsd">

一、配置Bean,以及从spring容器中获取Bean

  • 1、在xml中配置bean。
# 一个 <bean> 标签就表示一个bean对象,至少要含有id,class属性。
# id 表示 bean 对象的名称。 class 表示 bean 的类型。
<bean id="xxx" class="xxxxx"></bean>
  • 2、根据 id 获取 bean。
#在容器中,通过 id 获取 bean。
Object bean = contex.getBean("id");
  • 3、 根据 class 获取 bean。
#在容器中,通过 class 获取 bean。
#通过 class 类型获取 bean ,需要保证 IOC 容器中,该类型实例只存在一个。
Object bean = context.getBean("Hello.class");

二、注入Bean属性

  • 1、通过构造方法配置 bean 的属性。
#<constructor-arg> 标签来设置构造器注入
#value属性: 表示基础类型/string注入。
#ref属性: 表示对象类型注入。
#index属性: 表示参数的索引位置。
#type属性: 表示参数的类型.

<bean id="car" class="com.mz.Car">
     #<constructor-arg></constructor-arg>标签进行构造器方法注入
     <constructor-arg value="BYD" index="0" type="float"></constructor-arg>
     <constructor-arg value="1200" index="1" type="java.lang.String"></constructor-arg>
</bean>
  • 2、通过 setter 方法配置 bean 的属性。
#<property>标签来设置 setter 方法注入。
#使用 <ref> 标签或者 ref 属性进行注入属性对象。
<bean id="person" class="com.mz.Person">
	<property name="name" value="meng"></property>
	<property name="age" value="20"></property>
	<property name="car" ref="car"></property>
</bean>
  • 3、关于字面值,以及特殊字符的注入 value属性
    • 字面值:可以用字符串表示的值,可以通过 标签或者 value 属性进行注入。
    • 基本数据类型及其封装类, String 等类型都可以采取字面值注入方式。
    • 若字面值中包含特殊字符,可以使用 <![CDATA[]]> 把字面值包裹起来
<bean id="car1" class="com.mz.Car">
	<property name="name">
		<value><![CDATA[shanghai&&]]></value>
	</property>
	<property name="price" value="22000.3"></property>
</bean>
  • 4、关于对象类型的值的注入 ref属性
#使用 <ref> 标签或者 ref 属性进行注入属性对象。
<bean id="person" class="com.mz.Person">
	<property name="name" value="meng"></property>
	<property name="car" ref="car"></property>
</bean>

三、内置Bean

  • 内置Bean:即在中定义的bean。
  • 内置Bean,即使写有id属性,依然无法被外部bean所引用。
<bean id="person" class="com.mz.Person">
 	<property name="name">
 		<value>meng</value>
    </property>
    <property name="age" value="24"></property>
    <property name="car" >
     	 <bean  id="car" class="com.mz.Car">
      	  	<property name="name" value="audi"></property>
  		    <property name="price" value="30000"></property>
    	  </bean>
     </property>
</bean>


四、 级联属性赋值

  • 级联属性赋值:为成员属性对象的成员属性赋值。
  • 注意:属性需要先创建后才可以为可以为级联属性赋值。
 <bean id="person" class="com.mz.Person">
  	<property name="name" value="meng"></property>
  	<property name="age" value="20"></property>
  	<property name="car" ref="car"></property>
  	<!--级联属性赋值: 为属性对象的成员属性赋值。注意:属性需要先初始化后才可以为级联属性赋值。-->
  	<property name="car.price" value="2000"></property>
</bean>

五、集合属性赋值

  • 基础类型/string类型的属性注入使用 value 属性或者 标签。
  • 对象类型的属性注入使用 ref 属性或者标签。
  • 关于集合属性有: 数组,List,Set; Map; Properties;

数组,List,Set 集合属性注入

数组,List,Set 作为属性参数时,SpringIOC中配置都是用标签。

  • 格式
<property name="car">
	<list>
		<ref bean = "xxx" />
		<ref bean = "xxx" />
	</list>
</property>
  • 举例
@Data
public class Person {
	private String name;
	private Integer age;
	private List  carList;
}

#xml配置
<bean id="person" class="com.mz.Person">
	<property name="name" value="meng"></property>
	<property name="age"  value="24"></property>
	<property name="carList">
		<list>
			<ref bean="car"/>
            <ref bean="car1" />
        </list>
     </property>
</bean>

Map 集合属性注入

  • 使用标签,然后标签的key,value或者value-ref属性。
  • 也可以使用标签,然后标签的key属性,以及或者.
<bean id="person" class="com.mz.Person">
	<property name="name" value="meng"></property>
	<property name="age"  value="24"></property>
 	<property name="carMap">
    	<map>
			<entry key="car1" value-ref="car1"></entry>
			<entry key="car2">
				<ref bean="car"></ref>
			</entry>
		</map>
	</property>
</bean>

Properties 集合属性注入

  • properties类型,继承自HashTable,继承于Map接口。
  • 使用标签来定义j’a’va.util.properties,该标签使用作为子标签。每个中都必须定义key属性。
  • properties的特征是: key,value都是基础类型/string。
<bean id="person" class="com.mz.Person">
	<property name="name">
		<value>meng</value>
	</property>
	<property name="age" value="24"></property>
	<property name="datasource">
		<props>
			<prop key="user">root</prop>
			<prop key="password">1234</prop>
			<prop key="jdbcUrl">jdbc://mysql://test</prop>
			<prop key="driverClass">com.mysql.jdbc.Driver</prop>
		</props>
	</property>
</bean>

配置公共的集合对象,以便于其他对象的属性引用

  • 使用基本的几个标签定义集合时,不能将集合作为独立的bean定义,导致其他Bean无法引用该集合,所以无法在不同Bean之间共享集合。可以使用util schema里的集合 标签定义独立的集合Bean。需要在标签中加入util schema定义。
  • 配置单例的集合bean,以方便其他的bean作为属性引入,需要导入util命名空间。
<util:list  id="cars">
	<ref bean="car1"></ref>
	<ref bean="car2"></ref>
</util:list>

六、Bean属性的自动装配

xml配置的自动装配不建议使用

  • SpringIOC容器可以自动装配Bean,需要做的仅仅是在中设置autowire属性为指定自动装配的模式即可。
    Bean属性的自动装配,仅仅针对Bean的成员属性是对象类型的属性。

    • autowire = “byType” 是根据类型自动装配,若IOC容器中有多个与目标Bean的属性对象一致的Bean,Spring将无法判定那个Bean最适合该属性,自动装配将失效。
    • autowire =”byName”是根据名称自动装配,必须将目标Bean的名称和属性名设定的完全相同。根据Bean的"id属性"和"当前Bean的setter风格的属性名"进行自动装配,若有匹配,则进行自动装配,若没有匹配的,则不自动装配。
  • Bean自动装配的缺点:

    • 在Bean配置文件里面设置autowire属性进行自动装配,将会装配Bean的所有属性对象。不能单独指定某个属性。
    • autowire属性要么根据类型自动装配,要么根据名称自动装配,不能两者兼有。
    • 在实际的项目中很少使用自动装配功能,因为配置也会不清晰。
#如果配置有autowire自动装配,那么该Bean的所有对象类型的属性,都会自动进行属性装配。
<bean  id="person" class="com.mz.Person" autowire="byName">
</bean>

七、P命名空间直接代替来直接为属性设置初始化的值

  • 使用P命名空间,需要引入xmlns:p命名空间。
<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"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/p ">

  • 在标签中,使用p:属性 来代替
<bean id="person1" class="com.mz.Person" p:name="meng" p:age="24">
	<property name="carMap">
  		  <props>
                <prop key="key">value</prop>
           </props>
    </property>
</bean>
  • 使用 p:属性名=“xxx” 设置基础类型或者字符串,或者含有特殊字符的字符串。
#特殊字符串赋值,不需要[!CDATA[<SpecialString>]]
<bean id="xxx" class="xxx" p:name="meng" p:age="24"></bean>
<bean id="xxx" class="xxx" p:name="meng^&"></bean>  
  • 使用 p:属性名-ref = “xxx” 来引入对象
<bean id="xxx" class="xxx" p:car-ref="car"></bean>

八、Bean的抽象和继承配置

Spring允许继承Bean的配置,被继承的Bean被称为父Bean,继承这个父Bean的Bean称为子Bean。子Bean从父Bean中继承配置,包括Bean的属性配置。并不是元素里的所有属性都会被继承。比如:autowire,abstract等。子Bean也可以覆盖父Bean继承过来的配置。父Bean可以作为配置模板,也可以作为Bean的实例。若只想把父Bean作为模板,可以设置的abstract属性为true,这样Spring将不会实例化这个Bean。也可以忽略父Bean的class属性,让子Bean指定自己的类,而共享相同的属性配置,但此时abstract必须设为true。

  • Bean的继承使用 parent属性
    如果使用parent属性,那么子Bean会继承父Bean的所有属性配置。除了autowire,abstract。
<bean id="person" class="com.mz.Person"></bean>
<bean id="person1" class="com.mz.Person" parent="person"></bean>
  • 使用parent继承其他bean的配置的同事,也可以使用同名属性来覆盖继承来的bean属性。
<bean id="person2" parent="person" p:name="meng1" p:age="23"></bean>
  • 对于父类Bean,可以使用abstract属性来设置其是一个抽象bean。如果abstract=true,则SpringIOC容器不会创建该bean。则该父类bean,仅仅当做一个模板来使用。
    使用bean的abstract来表明这个bean是个模板,只能被继承使用。同时父bean是可以省略class不写的。
<bean id="person10" class="com.mz.Person" abstract="true" p:name="meng10" p:age="188" p:car-ref="car"></bean>
<bean id="person100" parent="person10"></bean>

九、Bean的作用域

  • Bean能设置的作用域 Scope属性
    • singleton 单例:
      默认值,容器初始化时创建bean实例,在整个容器的生命周期内只创建这一个bean,单例的。
    <bean id="xxx" class="xxx" scope="singleton"></bean>
    
    • prototype 原型 :
      原型的,容器初始化的时候后不创建这种scope的bean,而是每次请求的时候创建一个新的Bean,并返回。
    <bean  id="xxx"  class="xxxx"  scope="prototype"></bean>
    

十、外部属性文件配置properties的value

  • 在配置文件里配置Bean时,有时需要在Bean的配置里面混入系统部署的细节信息(文件路径,数据库配置信息等)。而这些部署细节实际上需要和Bean配置分离。Spring提供了一个PropertyPlaceHolderConfigure的BeanFactory后置处理器,这个处理器允许用户将Bean配置的部分内容外移到"属性文件"中,可以在Bean配置文件里使用形式为${var}的变量,PropertyPlaceholderConfigurer从属性文件里加载属性,并使用这些属性来替换变量。
  • Spring还允许在属性文件中使用${propName},以实现属性之间的相互引用。Spring2.5之后,可通过context:property-placeholder元素简化.
    • 在中添加context Schema定义。
    • 在配置文件中加入配置:<context:property-placeholder location=“classpath:xxx.properties” />
#没有使用外部配置文件的xml配置
<bean id="datasource" class="com.mz.DataSource">
	<property name="user" value="root"></property>
	<property name="password" value="123.com"></property>
	<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
	<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
</bean>
#使用xxx.properties外部文件引入属性配置
<context:property-placeholder location="classpath:Datasource.properties" />
<bean id="dataSource1" class="com.mz.DataSource">
	<property name="user" value="${user}"></property>
	<property name="password" value="${password}"></property>
	<property name="jdbcUrl" value="${jdbcUrl}"></property>
	<property name="driverClass" value="${driverClass}"></property>
</bean>

#xxx.properties文件中内容
user=meng
password=123.com
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/

十一、IOC容器中Bean的声明周期方法

  • SpringIOC容器可以管理Bean的生命周期,Spring允许在Bean的生命周期的特定点执行定制的任务。SpringIOC容器对Bean的生命周期进行管理的工程如下:
    • 1、通过构造器或者工厂方法创建Bean实例。
    • 2、为Bean的属性设置值,以及其他Bean的引用。
    • 3、调用Bean的初始化方法。(通过的init-method属性设置初始化方法。)
    • 4、Bean对象的获取,以及Bean对象的方法调用。
    • 5、当容器关闭时,调用Bean的销毁方法。(通过的destroy-method属性设置销毁方法。)
# xml中的设置
<bean id="car" class="com.mz.Car" init-method="init" destroy-method="destroy">
	<property name="name" value="BWM"></property>
	<property name="price" value="2000"></property>
</bean>

# javabean对象
public class Car {
    public void init(){
        System.out.println("开始创建");
    }

    public void destroy(){
        System.out.println("开始销毁");
    }
}

十二、创建Bean的后置管理器 BeanPostProcessor接口

  • Bean后置管理器允许在调用"初始化方法前后"对Bean进行额外的处理。
  • Bean后置管理器对SpringIOC容器里的所有Bean实例进行逐一处理,而非仅仅是针对某个实例。
  • 对Bean后置处理器而言,需要实现Interface BeanPostProcessor接口,在初始化方法被调用前后。Spring将每个Bean实例分别递给上述接口的一下两个方法:
    • (1) Object postProcessAfterInitialization( Object bean, String beanName );
    • (2) Object postProcessBeforeInitialization( Object bean, String beanName );
  • 加入Bean后置管理器之后的声明周期:
    • (1) 通过构造器或者工厂方法创建Bean实例。
    • (2) 为Bean的属性设置值,以及其他Bean的引用。
    • (3) 将Bean实例传递给Bean后置处理器的postProcessBeforeInitialization方法。
    • (4) 调用Bean的初始化方法。 #init-method属性
    • (5) 将Bean实例传递给Bean后置处理器的postProcessAfterInitialization方法。
    • (6) Bean对象的获取,以及Bean对象方法的调用。
    • (7) 当容器关闭时,调用Bean的销毁方法。 #destroy-method属性。

BeanPostProcessor后置管理器使用场景:

  • 对bean对象的检查,替换;
  • 对Bean对象属性的检查,替换;
# xml中的配置
# 配置BeanPostProcessor对象,不需要id,SpringIOC能自动识别,并且启动对象创建的后置管理。

<bean class="com.mz.MyBeanPostProcessor" ></bean>


# java实现BeanPostProcessor接口
 public class MyBeanPostProcessor implements BeanPostProcessor {
	
	//before方法,在init-method方法调用之前调用。
	@Override
	public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {

        System.out.println("before:"+o + " : "+s);
        if ( s.endsWith("car") ){
      	  Car car = (Car) o;
      	  car.setName("benz");
      	  car.setPrice(1000.0);
        }
        return o;
  	}
	
	//after方法,在init-method方法调用之后调用。
	@Override
	public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
	
        System.out.println("after:"+o + " : "+s);
        return o;
	}
}

十三、通过工厂方法配置bean

通过静态工厂方法来配置bean

# 通过静态工厂方法来配置bean.注意不是配置静态工厂方法实例,而是配置 bean 实例。
# id属性: 指静态工厂方法配置中的bean,是要获取对象的名称。(不是静态工厂方法对象的名字。)
# class属性: 指向静态工厂方法的全类名。
# factory-method: 指向静态工厂方法的名字。
# constructor-arg:如果静态工厂方法需要传入参数,则使用 constructor-org 来配置参数。((而不是静态工厂方法的构造函数。)

<bean id="car1" class="com.mz.staticCarFactory" factory-method="getCar">
	#静态工厂方法获取bean,constructor-arg为工厂方法传递参数。(而不是静态工厂方法的构造函数。)
	<constructor-arg value="audi"></constructor-arg>
</bean>


# java静态工厂类
# 静态工厂方法: 直接调用某一个类的静态方法就可以返回 Bean 的实例。
public class StaticCarFactory {

	private static Map<String,Car> cars = new HashMap<String,Car>();

	static {
		cars.put("audi", new Car("audi", 100000));
		cars.put("ford", new Car("ford", 200000));
	}
	
	//静态工厂方法
	public static Car getCar( String name ){
		return cars.get(name);
	}
}


# 获取bean实例,并且使用
public static void main( String[] args ){
	ApplicationContext ctx = new ClassPathXMLApplicationContext("beans-factory.xml");
	Car car1 = (Car)ctx.getBean("car1");
	System.out.println(car1);
}

通过实例工厂方法来配置bean

实例工厂方法: 实例工厂的方法,即需要创建工厂本身,再调用工厂的实例方法来返回 bean的实例。

# 第一步: 需要先配置工厂的实例
<bean id="car"  class="com.mz.InstanceCarFactory">
</bean>

# 第二步: 通过实例工厂方法来配置bean
<bean id="car2"  factory-bean="carFactory" factory-method="getCar">
	<constructor-arg  value="ford"></constructor-arg>
</bean>

# java实例的工厂类实现
public class  InstanceCarFactory {
	
	private Map<String,Car> cars = null;

	public InstanceCarFactory(){
		cars = new HashMap<String, Car>();
		cars.put("audi", new Car("audi", 3000));
		cars.put("ford", new Car("ford", 4000));
	}

	public Car  getCar( String brand ){
		return cars.get(brand);
	}
}


# 获取bean实例,并且使用
Car car2 = (Car)ctx.getBean("car2");
Systen.out.println(car2);

十四、通过FactoryBean配置bean

配置bean的时候bean有一个属性是引用的IOC容器中的其他bean的时候,通过FactoryBean配置bean。

# xml中对FactoryBean的配置
# 通过FactoryBean来配置Bean的实例
# class : 指向FactoryBean的全类名。
# property : 配置 FactoryBean 的属性。
# 但是实例返回的实例却是 Factorybean 的 getObject() 方法返回的实例。
		
<bean id="car" class="com.mz.CarFactoryBean">
	<Constructor-arg value="BWM"></Constructor-arg>
</bean>


# FactoryBean的实现
# 自定义的FactoryBean,需要实现FactoryBean接口。
public class CarFactoryBean implements FactoryBean<Car>{

	private String brand;
	public void setBrand(String brand){
		this.brand = brand;
	}

	//返回 bean 的对象
	public Car getOject() throws Exception {
		return new Car(brand, 50000);
	}
	
	//返回的 bean 的类型
	public Class<?> getObjectType(){
		return Car.class;
	}

	//是否是单例
	public boolean isSingleton(){
		return true;
	}
}


# 获取bean
ApplicationContext ctx = new ClassPathXmlApplicationContext("xxx.xml");
Car car = ctx.getBean("car");
System.out.println(car);

补充: 懒加载, 加载顺序

懒加载

  • 懒加载: 只针对spring创建bean时模式为单例时存在. 被标记为懒加载的实例,在容器启动的时候,不创建该bean实例。而是在第一次使用(获取)Bean时才创建单例Bean。
  • 基于xml配置的懒加载,只需要设置标签的 lazy-init属性为true即可。
<bean id="lazyBean" class="xxxx"  lazy-init="true">
</bean>

setter方式的属性注入时,指定加载顺序

todo 未完成
发布了58 篇原创文章 · 获赞 34 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_36723759/article/details/104080126