J2EE系列之Spring4学习笔记(五)--IOC详解(自动装配,方法注入,方法替换)

一、自动装配

通过配置default-autowire 属性,Spring IOC 容器可以自动为程序注入bean;默认是no,不启用自动装配;default-autowire 的类型有byName,byType,constructor;
byName:通过名称进行自动匹配;
byType:根据类型进行自动匹配;
constructor:和byType 类似,只不过它是根据构造方法注入而言的,根据类型,自动注入;
建议:自动装配机制慎用,它屏蔽了装配细节,容易产生潜在的错误;

1.新建工程Spring402-04;

2.新建类People:

package com.test.entity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class People {

	private int id;
	private String name;
	private int age;
	private Dog dog1;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	public Dog getDog1() {
		return dog1;
	}
	public void setDog1(Dog dog1) {
		this.dog1 = dog1;
	}
	@Override
	public String toString() {
		return "People [id=" + id + ", name=" + name + ", age=" + age + ", dog1=" + dog1.getName() + "]";
	}
	
	


	
	
}
3.新建类Dog:

package com.test.entity;

public class Dog {

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	
}

4.修改Spring配置文件:


这里开启了自动装配,采用按照名字自动装配的方式。定义了两个Dog对象dog1和dog2,定义了People对象people1,这里people1中并没有对Dog对象dog1进行装配。

5.写测试方法:

@Test
	public void test1() {
		People people = (People) ac.getBean("people1");
		System.out.println(people);
	}

运行测试方法:



可以看到这里给我们进行了自动装配。因为People中Dog对象的名字是dog1,所以这里给我们自动装配了dog1对象。


2)按照类型自动装配,修改Spring配置文件为:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd"
        default-autowire="byType">
	
	
	<bean id="dog2" class="com.test.entity.Dog">
		<property name="name" value="Tom"></property>
	</bean>
	<bean id="people1" class="com.test.entity.People">
		<property name="id" value="1"></property>
		<property name="name" value="张三"></property>
		<property name="age" value="11"></property>
	</bean>
	
</beans>

这里改成了byType通过类型自动装配,并删除了刚才定义的dog1对象。因为这里是根据类型进行装配,dog1和dog2类型相同都是Dog类型,所以如果保留着dog1对象的话,就会因为不知道要装配哪一个对象而报错。

运行测试方法test1:


这里根据类型把dog2对象进行了自动装配。


3)根据构造函数自动装配:根据类型进行装配

修改People类,添加构造方法:

public People() {
		super();
		// TODO Auto-generated constructor stub
	}
	public People( Dog dog1) {
		super();
		System.out.println("constructor");
		this.dog1 = dog1;
	}

这里给People类添加了构造方法,这里第二个构造方法利用Dog对象进行构造。

4.修改Spring配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd"
        default-autowire="constructor">
	
	
	<bean id="dog2" class="com.test.entity.Dog">
		<property name="name" value="Tom"></property>
	</bean>
	<bean id="people1" class="com.test.entity.People">
		<property name="id" value="1"></property>
		<property name="name" value="张三"></property>
		<property name="age" value="11"></property>
	</bean>
	
</beans>

这里自动装配改成了constructor利用构造函数自动装配。

运行测试方法:



这里运行了People的第二个构造方法,按照这个构造方法里面参数的类型进行了自动装配。


二、方法注入

这里提出一个这样的问题:Dog类中每次调用get方法都获取一个新的dog对象。

1.修改Spring配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	
	<bean id="dog" class="com.test.entity.Dog">
		<property name="name" value="Tom"></property>
	</bean>
	<bean id="people1" class="com.test.entity.People">
		<property name="id" value="1"></property>
		<property name="name" value="张三"></property>
		<property name="age" value="11"></property>
	</bean>
	
</beans>

这里把自动装配去掉。修改People类:

package com.test.entity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class People {

	private int id;
	private String name;
	private int age;
	private Dog dog1;
	
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	public Dog getDog1() {
		return dog1;
	}
	public void setDog1(Dog dog1) {
		this.dog1 = dog1;
	}
	@Override
	public String toString() {
		return "People [id=" + id + ", name=" + name + ", age=" + age + ", dog1=" + dog1.getName() + "]";
	}
	
	


	
	
}

先看一个测试方法:

@Test
	public void test1() {
		
		
		System.out.println(ac.getBean("dog")==ac.getBean("dog"));
	}
运行这个测试方法,输出true。这里取了两次Dog对象实例,这两个对象是同一个对象,这是因为在默认情况下Spring的IOC容器中对象是单例的。现在要去每次获取到的狗是一条新的狗,就不能使用单例形式。修改配置文件如下:

<bean id="dog" class="com.test.entity.Dog" scope="prototype">
		<property name="name" value="Tom"></property>
	</bean>

默认情况下scope属性的值是singleton,是单例的。现在修改成prototype,实现多例。


运行一下test1测试方法,程序输出为false。这样的话,每次在IOC容器中获取dog对象都是一个新的对象。现在修改Spring配置文件:

<bean id="people1" class="com.test.entity.People">
		<property name="id" value="1"></property>
		<property name="name" value="张三"></property>
		<property name="age" value="11"></property>
		
		<property name="dog1" ref="dog"></property>
	</bean>

这里使用ref属性给dog对象注入值。

写测试方法:

@Test
	public void test1() {
		People people = (People) ac.getBean("people1");
		People people2 = (People) ac.getBean("people1");
		System.out.println(people.getDog1()==people2.getDog1());
		
	}

运行这个测试方法,程序输出true。在配置文件中People类默认是单例的,所以这里people和people2是同一个对象,对于同一个对象的两次加载,Spring只调用一次Dog类的getDog方法,所以这里两个对象装配的dog实例是相同的。现在要求虽然这两个对象是相同的,但是给他们装配不同的dog对象,也就是实现Spring动态的调用getDog方法。这里要修改People类为:

package com.test.entity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public abstract class People {

	private int id;
	private String name;
	private int age;
	private Dog dog1;
	
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	public abstract Dog getDog1();
	
	public void setDog1(Dog dog1) {
		this.dog1 = dog1;
	}
	@Override
	public String toString() {
		return "People [id=" + id + ", name=" + name + ", age=" + age + ", dog1=" + dog1.getName() + "]";
	}
	
	


	
	
}

这里把People类定义成了抽象类,把getDog方法定义成了抽象方法。

修改Spring配置文件:

<bean id="people1" class="com.test.entity.People">
		<property name="id" value="1"></property>
		<property name="name" value="张三"></property>
		<property name="age" value="11"></property>
		<lookup-method name="getDog1" bean="dog"/>
	</bean>

这里使用<lookup-method>标签实现方法的动态注入,每次获取people1对象时Spring都会动态的去调用一次getDog1方法,这样因为Dog类的多例的,每次获取到的dog对象都是不同的。测试方法输出为false。


方法注入并不是常用。

三、方法替换

所谓方法替换就是Spring调用其它方法,而不是调用它本应该调用的方法。

修改People类如下:

package com.test.entity;

public class People {

	private int id;
	private String name;
	private int age;
	private Dog dog;
	
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	
	public Dog getDog() {
		Dog dog = new Dog();
		dog.setName("Jack");
		return dog;
	}
	public void setDog(Dog dog) {
		this.dog = dog;
	}
	@Override
	public String toString() {
		return "People [id=" + id + ", name=" + name + ", age=" + age + ", dog=" + dog.getName() + "]";
	}
	
	
}

我们这里给People类指定了Dog对象为名为Jack的狗。

定义一个类People2:

package com.test.entity;

import java.lang.reflect.Method;

import org.springframework.beans.factory.support.MethodReplacer;

public class People2 implements MethodReplacer{

	@Override
	public Object reimplement(Object arg0, Method arg1, Object[] arg2) throws Throwable {
		Dog dog = new Dog();
		dog.setName("Tom");
		return dog;
	}	
	
}

People2实现了接口MethodReplacer,并重写了其中的方法reimplement,在这个方法中返回一个名为Tom的狗。


修改Spring配置文件为:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	
	<bean id="people1" class="com.test.entity.People">
		<property name="id" value="1"></property>
		<property name="name" value="张三"></property>
		<property name="age" value="11"></property>
		<replaced-method name="getDog" replacer="people2"></replaced-method>
	</bean>
	
	<bean id="people2" class="com.test.entity.People2"></bean>
	
</beans>

这里实现people1时,使用people2中的方法替换getDog方法。


测试方法:

@Test
	public void test1() {
		People people = (People) ac.getBean("people1");
		System.out.println(people.getDog().getName());
	}
程序运行结果为Tom,这里实现了方法替换。使用了People2中的方法替换了People1中的getDog方法。


Spring中方法替换使用的也非常少。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值