Spring依赖注入三种方式及分析
按照Spring官网来说spring存在两种注入方式
1:构造函数注入
2:Setter注入
构造函数注入
@Component
public class ServiceB {
public ServiceB(){
System.out.println("B 调用了构造函数");
}
}
@Component
public class ServiceA {
private ServiceB serviceB;
public ServiceA(ServiceB serviceB) {
System.out.println("serviceB 被注入到ServiceA中");
this.serviceB = serviceB;
}
}
最后输出结果:
B 调用了构造函数
serviceB 被注入到ServiceA中
构造函数注入方式前提条件是注入对象(ServiceA)和被注入对象(ServiceB)都交由Spring托管。
当存在多个构造函数时,Spring默认选用无参构造函数创建Bean,导致构造函数注入不成功。
@Component
public class ServiceA {
private ServiceB serviceB;
public ServiceA(){
System.out.println("ServiceA 构造函数创建!!!");
}
public ServiceA(ServiceB serviceB) {
System.out.println("serviceB 被注入到ServiceA中");
this.serviceB = serviceB;
}
}
@Component
public class ServiceB {
public ServiceB(){
System.out.println("B 调用了构造函数");
}
}
输出结果
ServiceA 构造函数创建!!!
B 调用了构造函数
2.Setter注入
@Component
public class ServiceA {
private ServiceB serviceB;
public ServiceA() {
System.out.println("ServiceA 构造函数创建!!!");
}
@Autowired
public void setServiceB(ServiceB serviceB) {
System.out.println("serviceB 注入");
this.serviceB = serviceB;
}
}
@Component
public class ServiceB {
public ServiceB(){
System.out.println("B 调用了构造函数");
}
}
输出结果
ServiceA 构造函数创建!!!
B 调用了构造函数
serviceB 注入
@Autowired注解于方法上。
可能存在疑问:@Autowired注解于方法上和注解于字段上有什么区别?
我理解上注入方法和注入字段都可以叫setter注入。
- 注解在方法上最终是调用Method.invoke(object,args)调用setXXX方法注入。
- 注解在字段上最终调用Filed.set(XXXX);
3.@Lookup 方法注入
对于@Lookup修饰的方法,有相对应的标准
<public|protected> [abstract] <return-type> theMethodName(no-arguments);
public|protected要求方法必须是可以被子类重写和调用的
abstract可选,如果是抽象方法,CGLIB的动态代理类就会实现这个方法,如果不是抽象方法,就会覆盖这个方法
return-type是非单例的类型
no-arguments不允许有参数
这个注解有点鸡肋,目前好像还没有用到。包括一些常用的三方包里面也没有用到。当一个单例类(Singleton)
注入一个原型类(prototype)时,单例类里面所有的方法都是调用同一个原型类(prototype)实例.....大概等同于
@Component
public class ServiceA {
@Autowired
private ServiceB serviceB;
public int add(int i) {
return serviceB.add(i);
}
}
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ServiceB {
int i=1;
public int add(int j) {
return i= i + j;
}
}
ServiceA serviceA = context.getBean(ServiceA.class);
System.out.print(serviceA.add(1));
System.out.print(serviceA.add(2));
System.out.print(serviceA.add(3));
调用结果:
2
4
7
想要add()方法每次调用的对象实例都不一样就要用到@Lookup。
@Component
public class ServiceA {
public ServiceA() {
System.out.println("ServiceA 构造函数创建!!!");
}
@Lookup
public ServiceB createServiceB() {
return null;
}
public int add(int i) {
ServiceB serviceB = createServiceB();
return serviceB.add(i);
}
}
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ServiceB {
int i=1;
public ServiceB() {
System.out.println("B 调用了构造函数");
}
public int add(int j) {
return i= i + j;
}
}
ServiceA serviceA = context.getBean(ServiceA.class);
System.out.print(serviceA.add(1));
System.out.print(serviceA.add(2));
System.out.print(serviceA.add(3));
调用结果:
B 调用了构造函数
2
B 调用了构造函数
3
B 调用了构造函数
4
调用@Lookup标识的方法约等于直接从上下文中直接调用getBean()方法。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。