Использование синглтон-компонента с автопроводкой в ​​классе java без пружин - PullRequest
0 голосов
/ 29 марта 2020

Хорошо, это может показаться довольно глупым для всех ветеранов, но терпите меня здесь, так как я только пробираюсь через Spring & Spring Boot.

Здесь у меня есть класс Controller,

@RestController
public class Controller {

    private static final Logger logger = LogManager.getLogger(Controller.class);

    private static Controller controller = null;

    @Autowired
    private ApplicationParameters applicationParameters;

    public static Controller getInstance() {
        if (controller == null) {
            synchronized (Controller.class) {
                if (controller == null) {
                    controller = new Controller();
                }
            }
        }
        return controller;
    }

    public Controller() {}

    public ApplicationParameters getApplicationParameters() {
        return applicationParameters;
    }

    @RequestMapping("/")
    public void init() {
        try {
            for (Entry<String, String> prop : applicationParameters.getProperties().entrySet())
                logger.info("Loaded System Property: " + prop.getKey() + " -> " + prop.getValue());

                Utils.concatenate("key1", "key2");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }
} 

, который автоматически связывает бин ApplicationParameters со свойствами из файла свойств.

Класс утилит

public class Utils {

protected static final Logger logger = LogManager.getLogger(Utils.class);

    //Need to get the value of the property keys propKey1 & propKey2 and concat them.
    public static String concatenate(String propKey1, String propKey2) throws Exception {
        if(StringUtils.isNoneEmpty(propKey2) && StringUtils.isNoneEmpty(propKey1)) {
            return Controller.getInstance().getApplicationParameters().getProperties().get(propKey1) + Controller.getInstance().getApplicationParameters().getProperties().get(propKey2)
        } else {
            logger.error("System Property is undefined." );
            return null;
        }
    }

Итак, я хотел бы использовать этот автонастроенный компонент ApplicationParameters в качестве экземпляра singleton на протяжении всего жизненного цикла моего проекта.

Например, я хотел бы использовать его в классе Utils. Ясно, что Utils класс не управляется пружиной, это просто обычный старый класс java.

Поэтому я хотел бы знать, как использовать полностью инициализированные applicationParameters в моем классе Utils.

Это то, что я пробовал до сих пор:

  1. Автоматическое подключение ApplicationParameters снова в классе Utils, например,

    public class Utils {
    
    @Autowired
    private ApplicationParameters applicationParameters;
    
    protected static final Logger logger = LogManager.getLogger(Utils.class);
    

Но applicationParameters будет здесь null, поскольку, как я полагаю, это потому, что Utils не является бобом с пружинным управлением.

Сделать Controller класс синглтон. (Не уверен, как go делать это, так как init () должен вызываться при запуске веб-сервера, а затем, где вызывать getInstance ()?)

Следовательно, кто-то будет так добр чтобы помочь новичку здесь.

PS Класс Utils показан только в качестве примера, чтобы подчеркнуть тот факт, что в обычном java классе должен использоваться управляемый пружиной боб с автопроводкой.

Ответы [ 2 ]

1 голос
/ 29 марта 2020

Вы можете сделать контекст Spring доступным извне с помощью вспомогательного класса, подобного следующему:

public class SpringContextUtil implements ApplicationContextAware {
   static ApplicationContext applicationContext;     

   public void setApplicationContext(ApplicationContext context) throws BeansException {
     applicationContext = context;
   }

   public static ApplicationContext getApplicationContext() {
     return applicationContext;
   }
}

Затем вы можете сделать что-то вроде этого: SpringContextUtil.getApplicationContext.getBean("applicationParameters")

0 голосов
/ 29 марта 2020

Как правило, не надо. Второй тоже нет. Только если это действительно необходимо, поскольку нет гарантии, что это будет работать надежно, поскольку нет способа, чтобы все было правильно инициализировано при вызове этого метода. Вместо этого попробуйте переработать ваш утилит, чтобы стать классом с пружинным управлением.

Если вы действительно хотите, отбросьте большую часть своего кода, поскольку вы пытаетесь быть слишком умным в своем коде. Используйте этот хак (да, это хак имхо и его следует избегать при необходимости!).

public class SpringUtil {

  private static final ApplicationContext ctx;

  SpringUtil(ApplicationContext ctx) {
    SpringUtil.ctx=ctx;
  }

  public static Controller getController() {
    return this.ctx.getBean(Controller.class);
  }

  public static ApplicationParameters getApplicationParameters() {
    return ctx.getBean(ApplicationParameters.class);
  }
}

Затем очистите контроллер

@RestController
public class Controller {

    private static final Logger logger = LogManager.getLogger(Controller.class);

    @Autowired
    private ApplicationParameters applicationParameters;

    @GetMapping("/")
    public void init() {
        try {
            for (Entry<String, String> prop : applicationParameters.getProperties().entrySet())
                logger.info("Loaded System Property: " + prop.getKey() + " -> " + prop.getValue());

                Utils.concatenate("key1", "key2");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }
} 

Затем используйте SpringUtil для получения ApplicationParameters вместо контроллера

public class Utils {

protected static final Logger logger = LogManager.getLogger(Utils.class);

    //Need to get the value of the property keys propKey1 & propKey2 and concat them.
    public static String concatenate(String propKey1, String propKey2) throws Exception {
        if(StringUtils.isNoneEmpty(propKey2) && StringUtils.isNoneEmpty(propKey1)) {
            return SpringUtils.getApplicationParameters().getProperties().get(propKey1) + SpringUtils.getApplicationParameters().getProperties().get(propKey2)
        } else {
            logger.error("System Property is undefined." );
            return null;
        }
    }

Однако это довольно взломать и может работать в 90% случаев. Кроме того, в дизайне есть целый недостаток / запах, так как вы делаете много цепочек геттеров в своем классе. В общем, вам, вероятно, лучше реорганизовать Utils, чтобы использовать обычные вызовы методов и правильные методы проектирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...