简体   繁体   English

如何将 Spring 服务注入非组件父级 Class

[英]How to Inject a Spring Service into a Non-Component Parent Class

I have a parent class that is not managed by Spring which has multiple @Component 's inherited from it:我有一个父 class 不受 Spring 管理,它继承了多个@Component

public class Parent {

  public void commonMethod(SomeObj obj) {
    //...
  }
}

@Component
public class ChildA extends Parent {

  public MyObj doSomething(/*...*/) {
    // Some external call
    commonMethod(obj);
  }
}

@Component
public class ChildB extends Parent {

  public MyObj doSomething(/*...*/) {
    // Some external call
    commonMethod(obj);
  }
}

Now I need to call a Spring managed @Service from the Parent class. Of course, since Parent is not a Spring-managed bean, I was thinking to do something like:现在我需要从Parent class 调用 Spring managed @Service 。当然,由于Parent不是 Spring 管理的 bean,我想做类似的事情:

@Service
public class SomeServiceImpl implements SomeService {

  public void serviceWork(MyObj obj) {
    // Some static method call
  }
}

public class Parent {

  private SomeService someService;

  public Parent(SomeService someService) { this.someService = someService; }

  public void commonMethod(MyObj obj) {
    someService.serviceWork(obj);
    //...
  }
}

@Component
public class ChildA extends Parent {

  public ChildA(@Autowired SomeService someService) { super(someService); }
  
  public MyObj doSomething(/*...*/) {
    // Some external call
    commonMethod(obj);
  }
}

@Component
public class ChildB extends Parent {

  public ChildA(@Autowired SomeService someService) { super(someService); }

  public MyObj doSomething(/*...*/) {
    // Some external call
    commonMethod(obj);
  }
}

My question is, is this thread safe?我的问题是,这个线程安全吗? Second, is there a better design for this since now I have to @Autowired SomeService and pass it to Parent 's constructor for every child class.其次,是否有更好的设计,因为现在我必须@Autowired SomeService并将其传递给每个子 class 的Parent的构造函数。

Can I make the Parent class a Spring-managed class?我可以将Parent class 设为 Spring 管理的 class 吗? Would that cause any issues since now it becomes a singleton class that's being shared among all the children?这会导致任何问题吗,因为现在它变成了所有孩子共享的 singleton class?

You're confusing classes and instances of objects.您混淆了对象的类和实例。

Using your schema above you would have 3 objects instantiated使用上面的架构,您将实例化 3 个对象

1 instance of class SomeServiceImpl class SomeServiceImpl 的 1 个实例

1 instance of class ChildA (which happens to implement Parent) class ChildA 的 1 个实例(恰好实现了 Parent)

1 instance of class ChildB (which happens to implement Parent) class ChildB 的 1 个实例(恰好实现了 Parent)

This is because Spring will create these objects as they are defined as Components/Services.这是因为 Spring 将创建这些对象,因为它们被定义为组件/服务。 The 1 instance of SomeServiceImpl will be handed to both the instance of ChildA and the instance of ChildB. SomeServiceImpl 的 1 个实例将同时交给 ChildA 实例和 ChildB 实例。

Each instance of class ChildA and ChildB would have their own copy of all the data fields in their own class and all super classes. class ChildA 和 ChildB 的每个实例都有自己的 class 和所有超类中所有数据字段的副本。 However because you've auto wired the SomeServiceImpl they are pointing at the same instance of SomeServiceImpl.但是,因为您已经自动连接了 SomeServiceImpl,所以它们指向 SomeServiceImpl 的同一个实例。

So if you goal is to call SomeServiceImpl from ChildA and ChildB and have them thread safe this won't work since they are both talking to the same instance.因此,如果您的目标是从 ChildA 和 ChildB 调用 SomeServiceImpl 并让它们线程安全,这将不起作用,因为它们都在与同一个实例通信。

The general strategy looks correct, you'd have to mark the functions on SomeServiceImpl as synchronised.总体策略看起来是正确的,您必须将 SomeServiceImpl 上的功能标记为已同步。 Assuming it is that you want ChildA and ChildB to share the SomeServiceImpl.假设您希望 ChildA 和 ChildB 共享 SomeServiceImpl。

My question is, is this thread safe我的问题是,这个线程安全吗

no: Spring does not guarantee thread safety.否:Spring 不保证线程安全。 look at Are Spring objects thread safe?看看Spring 对象线程安全吗?

is there a better design for this since now I have to @Autowired SomeService and pass it to Parent's constructor for every child class.有没有更好的设计,因为现在我必须@Autowired SomeService 并将它传递给每个孩子 class 的父级构造函数。

public class Parent implements ApplicationContextAware {
 
private static ApplicationContext context;
public Parent() { this.someService = context.getBean(someService.class); }

But if parent need some bean maybe parent must be a bean to and let the appContext use DI但是如果parent级需要一些 bean 可能父级必须是一个 bean 并让 appContext 使用 DI

First of all, please have your future questions more focused and do not ask 5 questions in one post.首先,请您以后的问题更有针对性,不要在一个帖子中问5个问题。


How to Inject a Spring Service into a Non-Component Parent Class?如何将 Spring 服务注入非组件父 Class?

You cannot.你不能。

You cannot inject an object managed by Spring, into another object NOT managed by Spring.您不能将由 Spring 管理的 object 注入另一个不由 Spring 管理的 object。

Why?为什么? because, Spring has no idea what other objects in your program are, and hence, it will never have any reference(s) to them, unless they're also managed by Spring, ie they are bean s.因为,Spring 不知道你程序中的其他对象是什么,因此,它永远不会对它们有任何引用,除非它们由 Spring 管理,即它们是bean s。


My question is, is this thread safe?我的问题是,这个线程安全吗?

There is nothing about Thread-safety here.这里没有关于线程安全的内容。


Second, is there a better design for this since now I have to @Autowired SomeService and pass it to Parent's constructor for every child class?其次,是否有更好的设计,因为现在我必须 @Autowired SomeService 并将其传递给每个子 class 的父构造函数?

There are several ways of injection: Setter, Field, and Constructor.注入方式有几种:Setter、Field、Constructor。 Look it up in Google;在谷歌中查找;


Can I make the Parent class a Spring-managed class?我可以将 Parent class 设为 Spring 管理的 class 吗? Would that cause any issues since now it becomes a singleton class that's being shared among all the children?这会导致任何问题吗,因为现在它变成了所有孩子共享的 singleton class?

Yes, you can.是的你可以。 You can read Bean Definition Inheritance to see how.您可以阅读Bean Definition Inheritance了解如何操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM