最近为了提高自己开始学习spring框架,方便自己以后查询。
第一次写公开博客,排版辣鸡实非我意,善用Ctrl+F
配置bean
通过xml文件中的bean节点来配置bean:
<!--构造类名配置bean-->
<bean id="helloWorld" class="com.one.spring.beans.HelloWorld">
<property name="name" value="Spring"></property>
</bean>
<!--构造方法配置bean-->
<bean id="car" class="com.one.spring.beans.Car">
<constructor-arg value="Audi"></constructor-arg>
<constructor-arg value="Shanghai"></constructor-arg>
<constructor-arg value="300000"></constructor-arg>
</bean>
自定类:
public class HelloWorld {
private String name;
public void setName(String name) {
this.name = name;
}
public void hello(){
System.out.println(name);
}
}
public class Car {
private String brand;
private String corp;
private double price;
private int maxSpeed;
public Car(String brand, String corp, double price) {
this.brand = brand;
this.corp = corp;
this.price = price;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", corp='" + corp + '\'' +
", price=" + price +
", maxSpeed=" + maxSpeed +
'}';
}
}
main:
//1.创建Spring的IOC容器对象
ApplicationContext ctx=new ClassPathXmlApplicationContext("spring-config.xml");
//2.从IOC容器中l利用id获取Bean实例
HelloWorld helloWorld=(HelloWorld)ctx.getBean("helloWorld");
//3.调用hello方法
helloWorld.hello();
//利用类型返回IOC容器中的Bean,但要求IOC容器中只有一个该类型的Bean
Car car=ctx.getBean(Car.class);
System.out.println(car);
通过全类名配置:
class属性:bean的全类名,通过反射方式在IOC容器中创建Bean,要求一定要有一个无参的构造器。
id属性:标识容器中的bean,id唯一。
在IOC容器读取Bean配置创建Bean实例之前,必须对容器进行实例化,只有容器实例化之后,才可以从IOC容器里获取Bean实例并使用。
Spring提供了两种类型的IOC容器实现:
1.BeanFactory:IOC容器的基本实现。
2.ApplicationContext:提供了更多的高级特性,是BeanFactory的子接口,BeanFactory是Spring框架的基础设施,面向Spring本身,ApplicationContext面向使用Spring框架的开发者,几乎所有的场合都直接使用ApplicationContext。
3.ApplicationContext有两个主要实现类。
ClassPathXmlApplicationContext:从类路径下加载配置文件。
FileSystemXmlApplicaitionContext:从文件系统中加载配置文件。
ConfigurableApplicationContext扩展于ApplicationContext,新增两个主要方法,refresh()和close(),让Application具有启动、刷新和关闭上下文的能力。
依赖注入的方式:
1.属性注入:
属性注入即通过setter方法注入Bean的属性值或依赖的对象
使用元素,使用name属性指定Bean的属性名称,value属性或子节点指定属性值
属性注入使实际应用中最常用的注入方式
<bean id="helloWorld" class="com.one.spring.beans.HelloWorld">
<property name="name" value="Spring"></property>
</bean>
2.构造器注入:
通过构造方法注入Bean的属性值或依赖对象,它保证了Bean实例在实例化之后就可以使用。
构造器注入在元素里声明属性,中没有name属性。
<!--构造方法配置bean-->
<bean id="car" class="com.one.spring.beans.Car">
<constructor-arg value="Audi"></constructor-arg>
<constructor-arg value="Shanghai"></constructor-arg>
<constructor-arg value="300000"></constructor-arg>
</bean>
构造器注入可以通过中的index属性来声明注入顺序,也可以使用type属性来声明注入的数据类型,如:
<bean id="car" class="com.one.spring.beans.Car">
<constructor-arg value="Audi" index="0"></constructor-arg>
<constructor-arg value="Shanghai" index="1"></constructor-arg>
<constructor-arg value="300000.0" type="double"></constructor-arg>
</bean>
拥有多个含参构造器时,可以通过同时设置index和type属性来确定注入哪个构造器。
3.工厂方法注入(很少使用,不推荐):
(1)静态工厂方法:
调用静态工厂方法创建Bean是将对象创建的过程封装到静态方法中,当客户端需要对象时,只需要简单的调用静态方法,而不用关心创建对象的细节。
要声明通过静态方法创建的Bean,需要在Bean的class属性里指定拥有该工厂方法的类,同时在factory-method属性里指定工厂方法的名称,最后使用元素为该方法传递方法参数。
静态工厂方法类
public class StaticCarFactory {
private static Map<String,Car> cars=new HashMap<String, Car>();
static {
cars.put("audi",new Car("audi",300000));
cars.put("ford",new Car("ford",400000));
}
public static Car getCar(String name){
return cars.get(name);
}
}
-------------------------------------------------------------------------------------------------------------------------------------------------
Bean配置文件
<!--通过静态工厂方法来配置bean,注意不是配置静态工厂方法实例,而是配置bean实例-->
<!--
class属性:指向静态工厂方法的全类名
factory-method属性:志向静态工厂方法的名字
constructor-arg:如果工厂方法需要传入参数,则使用constructor-arg来配置参数
-->
<bean id="car1" class="com.one.spring.factory.StaticCarFactory"
factory-method="getCar">
<constructor-arg value="audi"></constructor-arg>
</bean>
(2)实例工厂方法:
将对象创建过程封装到另外一个对象实例的方法里,当客户端需要请求对象时,只需要简单的调用该实例方法而不需要关心对象创建的细节。
要声明通过实例工厂方法创建的Bean
-在Bean的factory-bean属性里指定拥有该工厂方法的bean
-在factory-method属性里指定该工厂方法的名称
-使用constructo-arg元素为工厂方法传递参数
工厂实例
public class InstanceCarFactory {
private Map<String,Car> cars=null;
public InstanceCarFactory(){
cars=new HashMap<String, Car>();
cars.put("audi",new Car("audi",300000));
cars.put("ford",new Car("ford",400000));
}
public Car getCar(String brand){
return cars.get(brand);
}
}
--------------------------------------------------------------------------
bean配置文件
<!--配置工厂的实例-->
<bean id="cars" class="com.one.spring.factory.InstanceCarFactory"></bean>
<!--通过实例工厂方法来配置bean-->
<bean id="car2" factory-bean="cars" factory-method="getCar">
<constructor-arg value="ford"></constructor-arg>
</bean>
两个方法最大的区别是,一个不创建工厂方法实例,直接配置bean实例;一个必须先配置工厂方法实例,然后再配置bean实例。
FactoryBean方法:
FactoryBean类:
public class CarFactoryBean implements FactoryBean<Car> {
private String brand;
public void setBrand(String brand) {
this.brand = brand;
}
@Override
public Car getObject() throws Exception{
return new Car(brand,500000);
}
@Override
public Class<Car> getObjectType(){
return Car.class;
}
@Override
public boolean isSingleton(){
return true;
}
}
XML文件:
<!--
通过FactoryBean来配置Bean的实例
class:指向FactoryBean的全类名
property:配置FactoryBean的属性
但实际返回的实例却是FactoryBean的getObject()方法返回的实例
-->
<bean id="car" class="com.one.spring.factorybean.CarFactoryBean">
<property name="brand" value="BMW"></property>
</bean>
</beans>
注入属性值的细节:
字面值:
即可以用字符串表示的值,可以通过元素标签或value属性进行注入
1.基本数据类型及其封装类,String等类型都可以采取字面值注入方式。
2.如果字面值包含特殊字符,可以使用<![CDATA[ ]]>包裹起来,例
<constructor-arg>
<value><![CDATA[<Shanghai>]]></value>
</constructor-arg>
引用其他的Bean:
组成应用程序的Bean经常需要互相协作以完成应用程序的功能,要使Bean能够互相访问,就必须在配置文件中指定Bean的引用
1.可以使用property的ref 属性/元素 建立Bean之间的引用关系,例
<bean id="person" class="com.one.spring.beans.Person">
<property name="name" value="Tom"></property>
<property name="age" value="24"></property>
<property name="car" ref="car"></property>
</bean>
2.也可以在属性或者构造器里包含Bean的声明,这样的Bean称为内部Bean,例
<bean id="person2" class="com.one.spring.beans.Person">
<property name="name" value="Tom"></property>
<property name="age" value="24"></property>
<property name="car">
<bean class="com.one.spring.beans.Car">
<property name="brand" value="Ford"></property>
<property name="corp" value="changan"></property>
<property name="price" value="200000"></property>
</bean>
</property>
</bean>
内部Bean不能够被外部引用,只能在内部使用,因此可以省去内部Bean的id属性。
注入参数详解:null值和级联属性
1.可以使用专用的元素标签为Bean的字符串或其他对象类型的属性注入null值
2.和Struts、Hiberante等框架一样,Spring支持级联属性的配置
<bean id="person" class="com.one.spring.beans.Person">
<property name="name" value="Tom"></property>
<property name="age" value="24"></property>
<property name="car" ref="car"></property>
<property name="car.maxSpeed" value="180"></property>//此处为级联属性赋值
</bean>
需要注意的是,属性需要先初始化后才可以为级联属性赋值,否则会有异常,和Struct2不同。
集合属性
1.在Spring中可以通过一组内置的xml标签,例如,或
以List为例:
外部引用
<bean id="person3" class="com.one.spring.bean.collection.Person">
<property name="name" value="Mike"></property>
<property name="age" value="27"></property>
<property name="cars">
<list>
<ref bean="car1"/>
<ref bean="car1"/>
<ref bean="car1"/>
</list>
</property>
</bean>
需要注意的是,ref引用的bean必须在同一个java包下。
内部Bean:
<bean id="person3" class="com.one.spring.bean.collection.Person">
<property name="name" value="Mike"></property>
<property name="age" value="27"></property>
<property name="cars">
<list>
<bean class="com.one.spring.bean.collection.Car">
<!--属性注入-->
</bean>
<bean class="com.one.spring.bean.collection.Car">
<!--属性注入-->
</bean>
</list>
</property>
</bean>
set和数组与list相似,不作额外记录。
Map:
通过
<bean id="newPerson" class="com.one.spring.bean.collection.NewPerson">
<property name="name" value="rose"></property>
<property name="age" value="28"></property>
<property name="carMap">
<map>
<entry key="AA" value-ref="car1"></entry>
<entry key="AB" value-ref="car"></entry>
</map>
</property>
</bean>
使用定义 ,该标签使用多个作为子标签,每个标签必须定义key属性:
可作为连接数据库的配置文件
<bean id="student" class="com.one.spring.beans.DataSource">
<property name="name" value="a"></property>
<property name="age" value="18"></property>
<property name="properties">
<props>
<prop key="username">xx</prop>
<prop key="password">xx</prop>
<prop key="driverclass">xx</prop>
<prop key="url">xx</prop>
</props>
</property>
</bean>
使用util配置独立的集合Bean,方便被多个Bean引用
<util:list id="cars">
<ref bean="car1"/>
<ref bean="car"/>
</util:list>
<bean id="person3" class="com.one.spring.bean.collection.Person">
<property name="name" value="Mike"></property>
<property name="age" value="27"></property>
<property name="cars" ref="cars"> </property>
</bean>
使用P命名空间:
为了简化xml文件的配置,越来越多的xml文件采用属性而费子元素配置信息。
P命名空间可以通过元素属性的方式配置Bean的属性。使用P命名空间后,基于XML的配置方式将进一步简化
<bean id="person5" class="com.one.spring.bean.collection.Person" p:age="12" p:name="test" p:cars-ref="car1"></bean>
自动装配:
使用自动装配来配置Bean
<bean id="address" class="com.one.spring.autowire.Address" p:city="BJ" p:street="HLG"/>
<bean id="car6" class="com.one.spring.autowire.Car" p:brand="Audi" p:price="300000"/>
<!--
可以使用autowire来指定自动装配的方式
byName 根据bean的名字和当前bean的setter方法属性名进行自动装配,若没有匹配的属性名,则为null
byType 根据bean的类型和当前bean的属性的类型进行自动装配,若有多个同类型属性,则抛出异常
-->
<bean id="person" class="com.one.spring.autowire.Person" p:name="Tom" autowire="byName"/>
</beans>
自动装配时,不能单独装配个别属性,不够灵活。
Spring-Bean之间的关系
1.继承
可以使用parent属性来继承大部分属性
<bean id="address" class="com.one.spring.autowire.Address" p:city="BJ" p:street="WDK"/>
<bean id="address2" parent="address" p:street="DZS"/>
可以使用abstract元素来让bean成为一个纯粹的只能被继承的bean:
<bean id="address3" abstract="true">
<property name="city" value="123"/>
<property name="street" value="321"/>
</bean>
<bean id="address4" class="com.one.spring.autowire.Address" parent="address3" p:city="312"/>
学习的时候,抽象bean中是可以使用p命名空间来进行属性注入的,我反复尝试了许多次都失败了,最后发现可以用依赖注入来代替
2.依赖关系:
Spring允许用户通过depends-on属性设定并前置依赖的Bean,前置依赖的Bean会在本Bean实例化之前创建好。如果前置依赖于多个Bean,则可以通过逗号,空格的方式配置Bean的名称。
<!--构造方法配置bean-->
<bean id="car" class="com.one.spring.beans.Car">
<constructor-arg value="Audi" index="1"></constructor-arg>
<constructor-arg value="Shanghai" index="0"></constructor-arg>
<constructor-arg value="300000" index="2"></constructor-arg>
</bean>
<!--要求在配置Person时必须要有一个关联的car,换句话说,依赖于car-->
<bean id="person" class="com.one.spring.autowire.Person" p:name="Tom" p:address-ref="address4" depends-on="car"/>
Bean的作用域:
利用bean的scope属性来配置bean的作用于
singleton:默认值,容器初始创建bean实例,在整个容器的生命周期内只创建这一个bean,单例的。
prototype:原型的,容器初始化时不创建bean的实例,而在每次请求时都创建一个新的Bean实例,并返回。
<bean id="car" class="com.one.spring.autowire.Car"
scope="singleton">
<property name="brand" value="Audi"/>
<property name="price" value="20000"/>
</bean>
Spring使用外部属性文件:
在配置文件里配置Bean时,有时需要在Bean的配置里混入系统部署的细节信息,如文件路径,数据源配置信息等,这些部署实际上需要和Bean配置分离。
Spring提供了一个PropertyPlaceholderConfigurer的BeanFactory后置处理器,这个处理器允许用户将Bean配置的部分内容外移到属性文件中,可以在Bean配置文件里使用形式为${brand}的变量,PropertyPlaceholderConfigurer从属性文件里加载属性,并使用这些属性来替换变量。
<context:property-placeholder location="classpath:db.properties"/>
<bean id="car" class="com.one.spring.autowire.Car">
<property name="brand" value="${brand}"/>
</bean>