如何为每个泛型类型创建一个bean的新实例?

时间:2017-12-23 05:54:39

标签: java spring

所以我有我的主题课:

@Component
public class Subject<T extends Monitorable> {

    @Autowired
    private List<Observer<T>> observers;

    public void fireListeners(T monitorable){
        for (Observer<T> observer : observers) {
            observer.doSome(monitorable);
        }
    }
}

这是为Monitorable的每个实现创建新主题实例的方法,如:

@Autowired
private Subject<Trip> tripSubject;

旅行是一个可以监视的,它有自己的观察员

@Autowired
private Subject<Truck> truckSubject;

和卡车

问题是。它只创建一个主题,所有观察者混合如何分离它们而不为每个监视创建一个新的主题类?

4 个答案:

答案 0 :(得分:1)

这不是你的问题的答案,但可能是你的问题的解决方案:Spring 4.2有一个内置事件(观察者)机制:

   @Autowire ApplicationEventPublisher publisher;
   public void doSomething() {
      ...
      //fire the event
      publisher.publishEvent(new YourEvent());
      ...
   }

其他一些bean:

   //This is the observer, it "catch" the event
   @EventListener
   public void handleOrderCreatedEvent(YourEvent your) {
        ...
   }

答案 1 :(得分:1)

这很简单。您可以通过几种方式完成此操作,其中一种方法是创建@Configuration并为每个必需实例定义单独的方法。

首先,请从@Component定义中删除Subject注释:

//@Component
public class Subject<T extends Monitorable> {
}

第二个,请使用@Configuration定义自定义配置:

@Configuration
public class MonitorableConfiguration {

    @Bean
    public Subject<Trip> tripSubject() {
        return new Subject<>();
    }

    @Bean
    public Subject<Truck> documentSubject() {
        return new Subject<>();
    }
}

第三次,请使用@Qualified选择Subject bean所需的实例:

@Service
public class BusinessLogicService {
    @Autowired
    @Qualifier("tripSubject")
    private Subject<Trip> tripSubject;
    @Autowired
    @Qualifier("documentSubject")
    private Subject<Truck> documentSubject;
}

注意 在这种情况下,我会建议再往前走一点。从我的角度来看,它可能更具可读性。

首先,请从@Component定义中删除Subject注释:

//@Component
public class Subject<T extends Monitorable> {
}

第二个,请为所有必需类型声明单独的class定义:

@Component
public class TripSubject extends Subject<Trip> {
}

@Component
public class TruckSubject extends Subject<Truck> {
}

第三次使用就像任何其他单身人士一样:

@Service
public class BusinessLogicService {
    @Autowired
    private TripSubject tripSubject;
    @Autowired
    private TruckSubject documentSubject;
}

答案 2 :(得分:1)

我改进了oleg.cheredinik的答案,因为没有办法做到这一点。这就是我认为最好的解决方案:

我将Subject更改为接收Observer作为构造参数

public class Subject<T extends Monitorable> {

    private final List<Observer<T>> observers;
    public Subject(final List<Observer<T>> observers) {
        this.observers = observers;
    }

    public void fireListeners(T monitorable){
        for (Observer<T> observer : observers) {
            observer.doSome(monitorable);
        }
    }
}

然后我用SubjectSimpleFactory:

创建了主题
@Configuration
public class SubjectSimpleFactory {

    @Bean
    @Autowired(required = false)
    public Subject<Trip> getTripSubject( Optional<List<Observer<Trip>>> observers){
        return new Subject<>(getListenersIfPresent(observers));
    }

    @Bean
    @Autowired(required = false)
    public Subject<Truck> getTruckSubject( Optional<List<Observer<Truck>>> observers){
        return new Subject<>(getListenersIfPresent(observers));
    }
}
private static <M extends Monitorable> List<Observer<M>> getListenersIfPresent(
        final Optional<List<Observer<M>>> observers )
    {
        return observers.isPresent() ? observers.get() : Collections.emptyList();
    }

通过这种方式,我的观察者不会混合,我只需要创建一个没有重复代码或子类Subject的类,我也可以使用泛型类型作为限定符

答案 3 :(得分:0)

@Service
@Scope("prototype")
public class Subject<T extends Monitorable> {

}

@Component
public class RunSubject {

    @Autowired
    private Subject<Monitorable1> subject1;

    @Autowired
    private Subject<Monitorabl2> subject2;

    public void run(ApplicationArguments args) throws Exception {
       System.out.println(subject1);
       System.out.println(subject2);
    }

 }