有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何将Spring上下文作为方法参数传递?

我需要一些关于Spring的帮助(SpringBoot 1.3.2.RELEASE,Spring 4.3.11.RELEASE)。 用例是特殊的,需要解释

我有一个Spring应用程序管理客户发送的请求。为了处理这些请求,我们需要使用@Autowired annotation声明的服务。非常经典

最近,我们决定处理来自其他国家的新类型请求。 关键是,为了面对不同的情况和类型的请求,我们决定实施一种策略模式。 -&燃气轮机;根据请求的类型,我们执行在运行时选择的策略。每个策略都包含在一个具体的类中,所有策略共享同一个接口

所以,我有:

  • 完全完成请求处理的主类。为了完成它的工作,这个类用来调用用@Autowired注释声明的一些服务

现在我有:

  • 一种只初始化请求处理的主类。做 在它的工作中,这个类将根据一些标准在运行时实例化单个策略
  • 一个IStrategy(接口),包含两种将要实现的方法 由我的两个具体类
  • 2个具体的课程(以及更多的课程)将完成这项工作非常重要的一点是,在加载Spring上下文后,这些具体类将在运行时实例化

问题是,在加载Spring上下文之后,就不可能再使用@Autowired注释了。 我想在我的具体策略类中使用的所有服务都不能再被@Autowired调用,并且保持为空

我找到了一个解决方法,将我需要的服务作为参数传递给我的具体策略类,但我必须作为参数传递的服务数量因策略而异

我想我应该通过整个春天的背景,但我不知道如何做到这一点。我也不知道如何从上下文访问所有带注释的服务

PS:我不显示代码行,因为我认为实际上没有必要。如果你认为代码会更明确,我会发送一些。

提前付款


共 (3) 个答案

  1. # 2 楼答案

    您可以使用下面的类静态地获取应用程序上下文和bean

    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.stereotype.Service;
    
    @Service
    public class BeanUtil implements ApplicationContextAware {
    
        private static ApplicationContext context;
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            context = applicationContext;
        }
        public static <T> T getBean(Class<T> beanClass) {
            return context.getBean(beanClass);
        }
    
    
    
    }
    
  2. # 3 楼答案

    大家好,你们很快就回答了我。 首先,我必须为最近回复你的评论而道歉。上一次冲刺的负荷很大,而新的冲刺并没有更好^^

    我的需要是在Spring上下文完成后创建on对象,以创建和加载应用程序的所有部分。 作为策略模式的一部分,我必须根据必须处理的请求文件中的某些值在运行时实例化一个类。这个类需要许多使用@Autowired注释声明的服务,但是所有自动连接的对象仍然是null,因为在加载上下文之后调用了它

    这是我第一次想要使用的代码。 没有弹簧也没问题

    Function<Document, IStrategy> func = doc -> {
            String strategyToApply = "";
            IStrategy strategy = null;
            switch(doc.getPlace()) {
                case "Paris":
                    strategyToApply = "strategies_classes.ProcessParis";
                    break;
                case "New York":
                    strategyToApply = "strategies_classes.ProcessNewYork";
                    break;
                }
                case "Roma":
                    ...
            try {
                **Class<?> classToUse = Class.forName(strategyToApply);
                strategy = (IStrategy) classToUse.newInstance();**
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            return strategy;
    };
    
    Consumer<Document> consumerStrategy = doc -> {
        IStrategy strategy = func.apply(doc);
        strategy.bookRequest(doc);
    };
    documents.stream()
        .forEach(consumerStrategy);
    

    我终于找到了那个神奇的东西。当Spring对象的生命周期不符合我们自己的概念时,这是一个很好的解决方法

    要使用它,您只需使用@Autowired:

    @Autowired
    private AutowireCapableBeanFactory autowireBeanFactory;
    

    请注意,AutowireCapableBeanFactory是一个Spring对象,您无需在其他任何地方声明

    然后,简单地使用它(我设计了一个全新的服务,与您在上面看到的非常不同,但它的功能相同):

    public <T> T getStrategyToUse(Entity bookingCtr, Funder funder, StrategyEnum strategy) throws FunctionalException {
            String strategyToApply = null;
            strategyToApply = strategyDao.getClassToApply(bookingCtr, funder, strategy);
            Class<?> classToUse;
            try {
                classToUse = Class.forName(strategyToApply);
                T strat = (T) **autowireBeanFactory.getBean**(classToUse);
                return (T) strat;
            } catch (ClassNotFoundException e) {
                LOGGER.error("The indicated Strategy class was not found", e);
            }
            return null;
        }
    

    当在运行时加载时,所选类将被实例化而不会出现任何问题,并且其所有自动连接对象将不再为null

    我希望这会有所帮助