1.通过setter方式注入
<!-- 配置一个 bean -->
<bean id="helloWorld2" class="com.atguigu.spring.helloworld.HelloWorld">
<!-- 为属性赋值 -->
<!-- 通过属性注入: 通过 setter 方法注入属性值 -->
<property name="user" value="Tom"></property>
</bean>
2.通过构造器注入
<!-- 通过构造器注入属性值 -->
<bean id="helloWorld3" class="com.atguigu.spring.helloworld.HelloWorld">
<!-- 要求: 在 Bean 中必须有对应的构造器. -->
<constructor-arg value="Mike"></constructor-arg>
</bean>
3.若一个 bean有多个构造器可以根据 index和 value进行更加精确的定位.
<bean id="car" class="com.atguigu.spring.helloworld.Car">
<constructor-arg value="KUGA" index="1"></constructor-arg>
<constructor-arg value="ChangAnFord" index="0"></constructor-arg>
<constructor-arg value="250000" type="float"></constructor-arg>
</bean>
4.若字面值中包含特殊字符,则可以使用 DCDATA来进行赋值.
<bean id="car2" class="com.atguigu.spring.helloworld.Car">
<constructor-arg value="ChangAnMazda"></constructor-arg>
<!-- 若字面值中包含特殊字符, 则可以使用 DCDATA 来进行赋值. (了解) -->
<constructor-arg>
<value><![CDATA[<ATARZA>]]></value>
</constructor-arg>
<constructor-arg value="180" type="int"></constructor-arg>
</bean>
5.通过ref 属性值指定当前属性指向哪一个 bean
<!-- 配置 bean -->
<bean id="dao5" class="com.atguigu.spring.ref.Dao"></bean>
<bean id="service" class="com.atguigu.spring.ref.Service">
<!-- 通过 ref 属性值指定当前属性指向哪一个 bean! -->
<property name="dao" ref="dao5"></property>
</bean>
6.声明内部bean
<!-- 声明使用内部 bean -->
<bean id="service2" class="com.atguigu.spring.ref.Service">
<property name="dao">
<!-- 内部 bean, 类似于匿名内部类对象. 不能被外部的 bean 来引用, 也没有必要设置 id 属性 -->
<bean class="com.atguigu.spring.ref.Dao">
<property name="dataSource" value="c3p0"></property>
</bean>
</property>
</bean>
7.设置级联属性
<bean id="action" class="com.atguigu.spring.ref.Action">
<property name="service" ref="service2"></property>
<!-- 设置级联属性(了解) 设置 service属性的dao属性的dataSource属性-->
<property name="service.dao.dataSource" value="DBCP2"></property>
</bean>
8.设置 属性值为 null
<bean id="dao2" class="com.atguigu.spring.ref.Dao">
<!-- 为 Dao 的 dataSource 属性赋值为 null, 若某一个 bean 的属性值不是 null, 使用时需要为其设置为 null(了解) -->
<property name="dataSource"><null/></property>
</bean>
9.配置List,Map,Properties
(1)在bean内部声明,声明后,即使给内部bean声明了id,其余bean也不可使用
<!-- 装配集合属性 -->
<bean id="user" class="com.atguigu.spring.helloworld.User">
<property name="userName" value="Jack"></property>
<property name="cars">
<!-- 使用 list 元素来装配集合属性 -->
<list>
<ref bean="car"/>
<ref bean="car2"/>
</list>
</property>
</bean>
(2)在外部声明集合类型的 bean,再引用
<!-- 声明集合类型的 bean -->
<util:list id="cars">
<ref bean="car"/>
<ref bean="car2"/>
</util:list>
<bean id="user2" class="com.atguigu.spring.helloworld.User">
<property name="userName" value="Rose"></property>
<!-- 引用外部声明的 list -->
<property name="cars" ref="cars"></property>
</bean>
10.使用p命名空间
使用p命名空间可简化 通过setter注入的写法
<bean id="user3" class="com.atguigu.spring.helloworld.User"
p:cars-ref="cars" p:userName="Titannic"></bean>
11.继承映射
(1)使用 parent 来完成继承,继承后,子bean可以覆盖从父bean继承过来的配置
(2)父bean作为模板,可设置bean 的abstract属性为true,这样spring不会实例化这个bean
(3)并不是<bean>元素里的所有属性都会被继承,比如autowire,abstract
(4)也可忽略父bean的class属性,让子bean设定自己的类,但此时abstruct属性必须为true
<bean id="user" class="com.atguigu.spring.helloworld.User">
<property name="userName" value="Jack"></property>
<property name="cars">
<!-- 使用 list 元素来装配集合属性 -->
<list>
<ref bean="car"/>
<ref bean="car2"/>
</list>
</property>
</bean>
<bean id="user4" parent="user" p:userName="Bob"></bean>
12.bean之间的依赖关系
Spring允许用户通过depends-on属性设定bean前置依赖的bean,前置依赖的bean会在本bean实例化前创建好
如果前置依赖多个bean,可通过逗号,或空格的方式配置bean的名称
<bean id="user6" parent="user" p:userName="维多利亚"></bean>
<!-- 测试 depents-on -->
<bean id="user5" parent="user" p:userName="Backham" depends-on="user6"></bean>
此示例中user5依赖于user6,
13.自动装配
Spring IOC容器可自动装配bean,需要在bean的autowire属性里指定自动装配的模式
byType(根据类型自动装配):若IOC容器中有多个与目标bean类型一致的bean,不能执行自动装配,会报错
byName(根据名称自动装配):必须目标bean的id和属性名设置的完全相同,若没有 id 一致的, 则无法完成自动装配
constructor:不推荐使用
(1)byName
Service类
public class Service {
private Dao dao;
public void setDao(Dao dao) {
this.dao = dao;
}
public Dao getDao() {
return dao;
}
public void save(){
System.out.println("Service's save");
dao.save();
}
}
xml配置文件
<!-- 在使用 XML 配置时, 自动装配用的不多. 但在基于 注解 的配置时, 自动装配使用的较多. -->
<bean id="dao" class="com.atguigu.spring.ref.Dao">
<property name="dataSource" value="C3P0"></property>
</bean>
<bean id="dao2" class="com.atguigu.spring.ref.Dao"></bean>
<bean id="service" class="com.atguigu.spring.ref.Service" autowire="byName"></bean>
此示例将自动注入id为 dao 的bean,给id为 service 的bean
(2)byType
Action类
public class Action {
private Service service;
public void setService(Service service) {
this.service = service;
}
public Service getService() {
return service;
}
public void execute(){
System.out.println("Action's execute...");
service.save();
}
}
xml配置文件
<bean id="service" class="com.atguigu.spring.ref.Service" autowire="byName"></bean>
<bean id="action" class="com.atguigu.spring.ref.Action" autowire="byType"></bean>
14.bean的作用域
可以通过 scope 属性来指定 bean 的作用域
prototype: 原型的. 每次调用 getBean 方法都会返回一个新的 bean. 且在第一次调用 getBean 方法时才创建实例
singleton: (默认值)单例的. 在 IOC 容器初始化时即创建 bean 的实例. 在整个容器的生命周期内,只创建一个bean
<bean id="dao2" class="com.atguigu.spring.ref.Dao" scope="prototype"></bean>
15.使用外部属性文件
(1).类路径下新建 db.properties 配置文件存放配置信息
jdbc.user=root
jdbc.password=1230
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///test
jdbc.initPoolSize=5
jdbc.maxPoolSize=10
(2).xml配置文件中导入外部属性文件,并使用文件中的属性(需使用context命名空间)
<!-- 导入外部的资源文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
</bean>
16.SpEL
(1)字面量表示
String可以使用单引号或者双引号作为字符串的定界符号:
<property name=“name” value="#{'Chuck'}"/>或<property name='name' value='#{"Chuck"}'/>
其余类型略...
(2)引用其他对象
(3)引用其他对象的属性
(4)调用其他方法,还可以链式操作
<!--通过value属性和spel 配置suffix属性值为另一个Bean的方法的返回值-->
<property name="suffix" value="#{sequenceGeneator.toString()}"></property>
(5)算数运算符:+,-, *, /, %, ^ (加号还可以用作字符串连接)
(6)比较运算符:<, >, ==, <=, >=, lt,gt,eq,le, ge
(7)逻辑运算符号: and, or, not
(8)if-else 运算符
(9)正则表达式:matches
(10)调用静态方法或静态属性:通过T() 调用一个类的静态方法,它将返回一个ClassObject,然后再调用相应的方法或属性:
示例:
<bean id="address" class="com.test.spel.Address">
<!-- 使用spel为属性赋一个字面值 -->
<property name="city" value="#{'beijing'}"></property>
<property name="street" value="huilongguan"></property>
</bean>
<bean id="car" class="com.test.spel.Car">
<property name="brand" value="Audi"></property>
<property name="price" value="500000"></property>
<!-- 使用SpEL引用类的静态属性 -->
<property name="tyrePerimeter" value="#{T(java.lang.Math).PI * 80}"></property>
</bean>
<bean id="person" class="com.test.spel.Person">
<!-- 使用spel引用一个其他的bean -->
<property name="car" value="#{car}"></property>
<!-- 使用spel引用一个其他bean的属性 -->
<property name="city" value="#{address.city}"></property>
<!-- 在spel中使用运算符 -->
<property name="info" value="#{car.price>300000? '金领':'白领'}"></property>
<property name="name" value="Tom"></property>
</bean>
17.Bean生命周期
Car实体类
public class Car {
private String brand;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
System.out.println("setter...");
this.brand = brand;
}
public Car(){
System.out.println("constructor...");
}
public void init(){
System.out.println("init...");
}
public void destory(){
System.out.println("destory...");
}
}
xml配置文件
<!-- 初始化方法:init-method 销毁方法:destroy-method -->
<bean id="car" class="com.test.cycle.Car"
init-method="init" destroy-method="destory">
<property name="brand" value="Audi"/>
</bean>
测试类:
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("beans-cycle.xml");
Car car=(Car) ctx.getBean("car");
System.out.println(car);
ctx.close();
}
结果:
先打印constructor...,再打印setter...,再打印init...,再打印com.test.cycle.Car@9317ccb,最后打印destory...
(2)Bean的后置处理器
1.实现接口BeanPostProcessor
public class MyBeanPostProcesser implements BeanPostProcessor{
/**
* init-method之前调用
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("postProcessAfterInitialization:" + beanName);
return bean;
}
/**
* init-method之后调用
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("postProcessBeforeInitialization:" + beanName);
return bean;
}
}
2.配置bean后置处理器
<!-- 实现接口 BeanPostProcessor 并提供
postProcessBeforeInitialization(Object bean, String beanName) init-method之前被调用
postProcessAfterInitialization(Object bean, String beanName) init-method之后被调用
方法的实现
-->
<!-- 配置bean的后置处理器,不需要配置id,IOC容器自动识别是一个 BeanPostProcesser-->
<bean class="com.test.cycle.MyBeanPostProcesser"></bean>
18.通过工厂方法配置bean
(1)静态工厂方法(不需要创建工厂的对象)
实体类Car
public class Car {
private String brand;
private int price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public Car(String brand, int price) {
super();
this.brand = brand;
this.price = price;
}
public Car() {
}
}
静态工厂StaticCarFactory
/**
* 静态工厂方法
* @author SkyWalker
*
*/
public class StaticCarFactory {
private static Map<String,Car> cars=new HashMap<>();
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);
}
}
xml配置文件
<!-- 通过静态工厂方法 配置bean实例 -->
<!--
class属性:指向静态工厂方法的全类名
factory-method:指向静态工厂方法的名字
constructor-arg:如果静态工厂方法需传入参数,则使用constructor-arg来配置参数
-->
<bean id="car1" class="com.spring.test.factory.StaticCarFactory"
factory-method="getCar">
<constructor-arg value="Audi"></constructor-arg>
</bean>
(2)实例工厂(需创建工厂的对象)
实体类Car:同上
实例工厂InstanceCarFactory
/**
* 实例工厂方法
* @author SkyWalker
*
*/
public class InstanceCarFactory {
private Map<String,Car> cars=null;
public InstanceCarFactory() {
cars=new HashMap<>();
cars.put("Audi", new Car("Audi",300000));
cars.put("Ford", new Car("Ford",400000));
}
public Car getCar(String brand) {
return cars.get(brand);
}
}
xml配置文件
<!-- 配置实例工厂 -->
<!--
factory-bean属性:指向实例工厂发方法的bean
factory-method:指向静态工厂方法的名字
constructor-arg:如果静态工厂方法需传入参数,则使用constructor-arg来配置参数
-->
<bean id="carFactory" class="com.spring.test.factory.InstanceCarFactory"></bean>
<!-- 通过实例工厂方法来配置bean -->
<bean id="car2" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="Ford"></constructor-arg>
</bean>
19.Spring 通过FactoryBean配置Bean
步骤:
1.实体类Car
public class Car {
private String brand;
private int price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public Car(String brand, int price) {
super();
this.brand = brand;
this.price = price;
}
public Car() {
}
}
2.写自定义的FactoryBean需要实现FactoryBean的接口
//自定义的FactoryBean 需要实现FactoryBean的接口
public class CarFactoryBean implements FactoryBean<Car>{
private String brand;
public void setBrand(String brand) {
this.brand = brand;
}
/**
* 返回bean的对象
*/
@Override
public Car getObject() throws Exception {
// TODO Auto-generated method stub
return new Car(brand,500000);
}
/**
* 返回bean的类型
*/
@Override
public Class<?> getObjectType() {
return Car.class;
}
/**
* 是否单例
*/
@Override
public boolean isSingleton() {
return true;
}
}
3.xml配置文件
<!--
通过FactoryBean来配置Bean的实例
class: 指向FactoryBean的全类名
property:配置FactoryBean的属性
但实际返回FactoryBean的getObject()方法返回的实例
-->
<bean id="car" class="com.spring.factorybean.CarFactoryBean">
<property name="brand" value="BMW"></property>
</bean>