在抽象基类中使用@autowired
据我所知,不建议进行field injection
。 应该使用constructor
。
我在这里尝试做的是在基类的构造函数中使用@Autowired
,并使其可供所有子类访问。 在某些子类中,我还需要一些特定的bean来从它们的构造函数中@Autowired
。 演示代码如下:
基类:
public abstract class Base { protected final MyDemoService myDemoService; @Autowired public Base(MyDemoService myDemoService) { this.myDemoService = myDemoService; } }
inheritance(子)类:
public class Sub extends Base { private final MySubService mySubService; @Autowired public Sub(MySubService mySubService) { this.mySubService = mySubService; } }
这将给我一个’无默认构造函数’错误。
它类似于问题: 类似的问题和答案 ,但它在这里不起作用。
我已经潜入了一段时间,我发现这篇关于dependency injection
文章: 进一步阅读
我认为Setter Injection
是我问题的正确方法吗?
塞特犬注射:
public abstract class Base { protected MyDemoService myDemoService; @Autowired public void setMyDemoService(MyDemoService myDemoService) { this.myDemoService = myDemoService; } }
我是Java Spring Boot的新手,想要从你们那里获得一些专业知识。 任何讨论都将受到高度赞赏!
您提供的代码将无法编译。 只要在您的基类中没有默认构造函数,就应该在子级中调用super(MyDemoService)
。
inheritance(子)类:
public class Sub extends Base { private final MySubService mySubService; @Autowired public Sub(MySubService mySubService, MyDemoService myDemoService){ super(myDemoService); this.mySubService = mySubService; } }
或者,如果MySubService
是MySubService
的实现
@Autowired public Sub(MySubService mySubService){ super(mySubService); }
只要抽象类中的字段MyDemoService myDemoService
protected
您就可以在子类中使用它。
如果您有多个MyDemoService
实现, MyDemoService
您必须使用@Qualifier
,如您提到的答案中所述 。
public Sub(@Qualifier("MySubService") MyDemoService mySubService){ super(mySubService); }
不要使用字段注入,使用构造函数注入调用适当的超级构造函数。
构造函数注入确保在实例化之前正确填充对象,setter注入不会使代码更容易出错(不是另一个nullpointer bug ….)
如果你担心你必须编写的额外代码,那么使用Project Lombok让Lombok为你生成构造函数代码,如下所述为什么字段注入是邪恶的
从Spring 4开始,如果你的类中只有一个构造函数,那么构造函数中不需要@Autowired。
我建议使用@Configuration
类。 这样您就可以完全从业务类中删除Spring注释:
public class Sub extends Base { private final MySubService mySubService; public Sub(MySubService mySubService, MyDemoService myDemoService){ super(myDemoService); this.mySubService = mySubService; } }
Spring配置:
@Configuration public class SubConfig{ @Bean public Sub sub(MySubService subService, MyDemoService demoService){ return new Sub(subService, demoService); } }
使用Configuration类,您不再依赖于神奇的类路径扫描,而是再次手动实例化bean。 这种方法的惊喜要少得多。
你不能用构造函数注入这样做,你必须使用Base类构造函数的依赖项扩展子类构造函数,并调用正确的super
构造函数(标准Java规则仍然适用,即使你使用Spring)。
然而,Field和Setter注入将正确地执行此操作。
在任何情况下我都会建议使用Field注入,因为它可以减少代码重复。 相比:
class A { @Autowired private Field field; }
比。
class A { private final Field field; /** plus mandatory javadocs */ @Autowired public A(Field field) { this.field = field; } }
在构造函数注入示例中,您重复自己四次只是为了让字段按照您想要的方式设置…即使我喜欢最终的事情,这种重复只会让代码变得难以改变。