Spring Framework

注:所有xml省略spring格式,需添加


IOC的XML配置详解

配置bean示例

xml如下:

1
<bean id="impl别名" class="impl的全类名"/>

java如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
//这是被注入对象
class java {
    public static void main(String[] args) {
        //获取IOC容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("xml文件名");
        //获取bean
        目标对象接口 对象名 = (目标对象接口类型强转) ctx.getBean("xml中的id属性值");
        对象名.成员方法;
    }
}

DI的XML配置详解

xml部分

1
2
3
4
5
6
<!--给A注入B,A中包含B对象-->
<bean id="A别名" class="A全类名"/>
<bean id="B别名" class="B全类名">
<property name="A类中的B对象名" ref="A别名"/>
<!--将name值反过来也可以实现反向注入-->
</bean>

java部分

1
2
3
4
5
6
class java {
    //提供set方法注入对象
    public void set被注入对象名(对象类型 对象名) {
        this.对象名 = 对象名;
    }
}

bean配置

基本属性

属性名属性作用
id获取唯一的bean,相当于别名,唯一
class全类名,bean类型
name真正意义上的别名,可以用空格分割多个别名,影响getBean方法
scope可选prototype非单例或者singleton单例

bean实例化

构造方法

spring默认调用空参构造方法进行对象实例化,通过反射调用内部构造方法

静态工厂

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class 对象Factory{
    public static 对象接口 get对象(){
        //工厂初始化行为代码
        return new 对象impl();
	}
}
class AppForInstance对象名{
    public static void main(String[] args) {
        ApplicationContext applicationContext = new  ClassPathXmlApplicationContext("application.xml");
		对象接口 对象名 = applicationContext.getBean(对象接口名);
        对象名.成员方法;
    }
}
1
<bean id="bean唯一标识" class="工厂全类名" factory-method="get对象的方法名"/>

示例工厂

旧版本:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class 对象factory{
    public 对象接口 get对象接口(){
        return 对象impl();
	}
}
class AppForInstance对象名{
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
        对象接口 对象名 = applicationContext.getBean(对象接口名);
        对象名.成员方法;	
    }
}
1
2
    <bean id="工厂唯一标识" class="工厂全类名"/>
    <bean id="bean唯一标识" factory-method="get对象方法名" factory-bean="工厂唯一标识"/>

新版本:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
public class 对象FactoryBean implements FactoryBean<对象>{
    //重写方法
	public 对象 getObject() throws Exception{
        //代替原始工厂中代替创建方法
		return new 对象impl();
	}
    public Class<?> getObjectType(){
        return 对象.class;
	} 
    public boolean isSinglenton(){
        return true;//是否开启单例
	}
}
class AppForInstance对象名{
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
        对象接口 对象名 = applicationContext.getBean(对象接口名);
        对象名.成员方法;
    }
}
1
<bean id="对象标识" class="FactoryBean全类名"/>

bean生命周期

旧版本:

1
2
3
4
5
6
7
8
public class 对象impl{
    public void init(){
        //初始化
	}
    public void destory(){
        //销毁
	}
}
1
<bean id="唯一标识" class="全类名" init-method="init" destory-method="destory"/>

若要调用destory方法需要在虚拟机关闭前执行容器关闭,有两种方式

  1. 直接调用ApplicationContext接口对象无法调用close对象进行销毁,需要将对象换成 ClassPathXmlApplicationContext接口对象并调用close方法关闭容器从而实现close方法
  2. 创建完ApplicationContext对象后,调用对象.registerShutdownHook成员方法注册关闭钩子,当虚拟机停止运行前会自动关闭容器并调用destory方法

新版本:

1
2
3
4
5
6
7
8
9
public class 对象impl implements 对象接口,InitializingBean,DisposableBean{
    //重写方法
	public void afterPropertiesSet(){//这里的set是指set对象()方法之后
        //init内容
	}
    public void destory(){
        //destory内容
	}
}

DI详解

多个对象注入方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
public class A{
    public void doit(){
        System.out.println();
	}
}
public class B{
    public void doit(){
        System.out.println();
    }
}
public class DItest{
    private A a;
    private B b;
    void setA(A a){
        this.a=a;
	}
    void setB(B b){
        this.b=b;
    }
}
1
2
3
4
5
6
<bean id="A" class="A全类名"/>
<bean id="B" class="B全类名"/>
<bean id="DItest" class="DItest全类名">
<property name="a" ref="A"/>
<property name="b" ref="B"/>
</bean>

setter注入

可选依赖使用setter注入,灵活性强

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class 对象impl{
    private int i;
    private String s;
    public void setI(int i){
        this.i = i;
	}
    public void setS(int s){
        this.s = s;
	}
}
1
2
3
4
<bean id="唯一标识" class="全类名">
	<property name="i" value="520"/>
	<property name="s" value="你好"/>
</bean>

构造器注入

spring强制依赖使用构造器进行依赖注入,setter注入方式有概率造成null错误

标准书写

对象注入

1
2
3
4
5
6
7
public class B{
    private A a;
    public DItest(A a){
        this.a=a;
        //有参构造
	}
}
1
2
3
4
5
6
<!--将A注入到B-->
<bean id="A" class="A全类名">
<bean id="B" class="B全类名">
	<constructor-arg name="B类构造器里的A参数" ref="A别名"/>
<!--	注入多个bean就增加多个参数并且添加本条list-->
</bean>

变量注入

1
2
3
4
5
6
public class DItest{
    private String s;
    public DItest(String s){
        this.s=s;
	}
}
1
2
3
<bean id="DItest" class="全类名">
    <constructor-arg name="构造器里的变量名" value="值"/>
</bean>

简便写法

  1. java部分不变,解决形参名耦合问题
1
2
3
4
<bean id="DItest" class="全类名">
    <constructor-arg type="int" value="值"/>
<!--	用type属性指代参数类型,对应构造器变量-->
</bean>
  1. java部分不变,解决类型重复问题
1
2
3
4
<bean id="DItest" class="全类名">
    <constructor-arg index="0" value="值"/>
<!--	从零开始,按照索引为构造器参数赋值-->
</bean>

自动装配

按类型装配与按名称装配:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class A{
    private B b;
    public setB(B b){
        this.b = b;
	}
}
public java{
    ApplicationContext context = new ClassPathXmlApplicationContext("application.properties");
    A a = (A)context.getBean("a");
    a.成员变量;
}
1
2
3
4
<bean id="b" class="B全类名"/>
<bean id="a" class="A全类名" autowire="byType"/>
<!--按类型装配不可有多个符合条件的类-->
<bean id="a" class=""/>