依赖注入和循环依赖注入
依赖注入和循环依赖注入
1.java bean注入的两种方式
1.1 Resource注解方式
@Resource
private NestedComponent nestedComponent2;
1.2 构造器注入的方式来
private NestedComponent nestedComponent1;
// 构造器注入的方式来 @Resource java: 注释类型不适用于该类型的声明
@Autowired public OuterComponent(NestedComponent nestedComponent1) { this.nestedComponent1 = nestedComponent1; }
1.3 //自己注入自己 报错了 Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.
NestedComponent ss = (NestedComponent)(AopContext.currentProxy());
1.4 以上两种方式需要在容器中运行才可以执行。而不能运行main方法。
package com.mytest.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import javax.annotation.Resource; /** * 在主类中定义内部类 剥离出去,形成独立的类,否则就会报下面的错误。 The dependencies of some of the beans in the application context form a cycle: ┌─────┐ | outerComponent defined in file [D:\git\version3\mytest\mytestDock-service\build\classes\java\main\com\mytest\service\OuterComponent.class] ↑ ↓ | com.mytest.service.OuterComponent$NestedComponent └─────┘ */ 独立的类 package com.mytest.service; import org.springframework.stereotype.Component; @Component public class NestedComponent { } @Component //@Service public class OuterComponent { private NestedComponent nestedComponent1; // 构造器注入的方式来 @Resource java: 注释类型不适用于该类型的声明 @Autowired public OuterComponent(NestedComponent nestedComponent1) { this.nestedComponent1 = nestedComponent1; } public OuterComponent() { } //使用字段注入 // @Autowired // @Resource // private NestedComponent nestedComponent2; // 使用nestedComponent的方法... //剥离出去,形成独立的类,否则就会报上面的错误。 // @Component // public class NestedComponent { // // NestedComponent的实现... // } public void print1(){ System.out.println("nestedComponent1=" + nestedComponent1.toString()); } // public void print2(){ // System.out.println("nestedComponent2=" + nestedComponent2.toString()); // } // public static void main(String[] args) { // OuterComponent outer = new OuterComponent(); //// outer.print1(); // outer.print2(); // } }
1.相互嵌套注入,spring中可以,不会报错
package com.mytest.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * 在Spring等依赖注入框架的帮助下,循环依赖可以被正确解决,但在没有使用这些框架的情况下,需要手动管理依赖关系,避免循环依赖的发生。 * 使用setXXX方式注入对象 */ @Component public class ClassA { /** * 使用依赖查找或注入框架:比如Spring框架,它可以管理对象的生命周期,并解决循环依赖问题。 */ @Autowired private ClassB b; public ClassA() {} } package com.mytest.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class ClassB { @Autowired private ClassA a; public ClassB() {} }
2.手动管理依赖关系
1.构造函数的方式会报错
package com.example.core.mydemo.bean; public class ClassB { public ClassA a; public ClassB() { super(); a = new ClassA(); } } package com.example.core.mydemo.bean; public class ClassA { private ClassB b; /** * 构造函数注入:使用构造函数来传递依赖,而不是使用字段注入或方法注入。 会相互依赖的注入初始化对象 */ public ClassA() { super(); b = new ClassB(); } public static void main(String[] args) { ClassA a = new ClassA(); System.out.println("b=" + a.b.toString()); ClassB b = new ClassB(); System.out.println("a=" + b.a.toString()); } }
output循环打印报错信息:
Exception in thread "main" java.lang.StackOverflowError
at com.example.core.mydemo.bean.ClassB.<init>(ClassB.java:8)
at com.example.core.mydemo.bean.ClassA.<init>(ClassA.java:11)
at com.example.core.mydemo.bean.ClassB.<init>(ClassB.java:8)
at com.example.core.mydemo.bean.ClassA.<init>(ClassA.java:11)
2.使用setXXX方法可以初始化对象
package com.example.core.mydemo.bean; public class ClassB { public ClassA a; public ClassB() {} /** * 使用setter方法注入:先创建对象,然后使用setter方法设置依赖。 * @param a */ public void setA(ClassA a) { this.a = a; } } package com.example.core.mydemo.bean; public class ClassA { private ClassB b; public ClassA() {} /** * 使用setter方法注入:先创建对象,然后使用setter方法设置依赖。 这种方式可以控制 // * @param b */ public void setB(ClassB b) { this.b = b; } public static void main(String[] args) { ClassA a = new ClassA(); ClassB b = new ClassB(); a.setB(b); System.out.println("b=" + a.b.toString()); b.setA(a); System.out.println("a=" + b.a.toString()); } }
output打印信息:
b=com.example.core.mydemo.bean.ClassB@65b3120a
a=com.example.core.mydemo.bean.ClassA@6f539caf