前面我们的bean都是自己手动配置注入的,Spring提供有可以自动配置的机制:通过配置default-autowire属性,Spring IOC 容器可以自动为程序注入bean,默认是:no,不启动自动装配;default-autowire的类型有byName,byType,constructor
建议:自动装配机制要慎用,它屏蔽了装配细节,容易产生潜在的错误。
根据名字是否一样来自动装配注入。
还是之前用的那个例子:Person类属性:id,name,age,dog; Dog类中属性:name.
现在在beans.xml添加属性:
default-autowire="byName"
xml里面有一个person的bean,两个dog的bean:
可以看到person1里面的dog属性根本没有配置注入,但由于是byName自动注入,IOC容器会自动装配名字(id)为dog的bean,而不会注入名字不同(id为dog1)的bean.
测试:
@Test
public void test1() {
Person person = (Person)ac.getBean("person1");
System.out.println(person);
}
id为dog的属性的值:Jack 被自动装配了进来。
根据类型是否一致来自动装配注入,需要注意的是如果同一种类型的多个bean存在,就会报错。
在beans.xml替换为:
default-autowire="byType"
如果按照上面的,xml里面有一个person的bean,两个dog的bean:就会报错:
去掉一个后在测试就不报错了:
与byType相似,只不过他是根据构造方法注入而言的,根据类型,自动注入。
往bean.xml替换为:
default-autowire="constructor"
在entity中写一个构造方法:
public Person(Dog dog) {
super();
System.out.println("constructor...");
this.dog = dog;
}
如果使用了此构造方法,就会在控制台打印出"constructor..."
同时在xml中:
测试;
Spring默认管理的bean都是以单实例存在的(作用域默认是单例 singleton),容器里只有一个实例。
可以通过配置prototype,实现多例。-----scope="prototype"
我们来看一下默认的情况:
通过两次获取bean,在控制台上打印是否相等来判断两次获取的实例是否为同一实例
System.out.println(ac.getBean("dog")==ac.getBean("dog"));
打印结果为true,说明两次获取的实例是同一实例。
配置prototype后:
为false,说明两次获取的实例不是同一实例。每次都是取得一个新的bean。
但是 ,如果把dog注入到person中,两次通过person来获取dog,两次获取的dog是否一样呢?
测试:
@Test
public void test1() {
Person person = (Person)ac.getBean("person1");
Person person1 = (Person)ac.getBean("person1");
//比较两次通过person获得的dog(配置了prototype属性)是否为同一实例
System.out.println(person.getDog()==person1.getDog());
//比较直接获取dog(配置了prototype属性)是否为同一实例
System.out.println(ac.getBean("dog")==ac.getBean("dog"));
}
}
结果:
出现这样的原因是:底层已经固定好注入的bean,默认是不能动态的改变的,但是Spring有机制是可以实现动态的注入的。
通过配置
首先要把要动态注入的方法抽象化(abstract) ,所以类也变成抽象类。具体实现由Spring来实现。
public abstract class Person {
public abstract Dog getDog() ;
在注入时:
name为方法名
结果:
我们发现这样就能实现动态注入方法,每次通过方法获取的都是一个新实例。不过在日常开发中并不常见。
通过实现MethodReplacer接口,重写里面的reimplement方法,来实现方法的替换。reimplement方法写要替换的方法的内容
具体通过下面实例:
我们定义两个person,把里面的getDog方法写死,就让它返回指定的名字。
person 里面的getDog():
public Dog getDog() {
Dog dog = new Dog();
dog.setName("Jack");
return dog;
}
person2:
import java.lang.reflect.Method;
import org.springframework.beans.factory.support.MethodReplacer;
public class Person2 implements MethodReplacer{
@Override
public Object reimplement(Object arg0, Method arg1, Object[] arg2) throws Throwable {
Dog dog = new Dog();
dog.setName("Tom");
return dog;
}
}
配置:
这样就可以实现通过person1 的getDog方法替换成person2的方法内容。
测试:
@Test
public void test1() {
Person person = (Person)ac.getBean("person1");
System.out.println(person.getDog().getName());
}
可以获得reimplement方法里的内容。开发中不常用,不过也要了解一下,万一用到也有个想法。
内容总结来源:Java1234学习路线