Использование репозиториев данных Spring в статических методах - PullRequest
0 голосов
/ 21 декабря 2018

Я определил 2 класса.

AndroidPush.java

public class AndroidPush {

    private static String SERVER_KEY = "XXXXX";
    private static String DEVICE_TOKEN = "XXXXX";
    public static void main(String[] args) throws Exception {
        String title = args[0];
        String message = args[1];
        sendPushNotification(title, message);
    }
    private static void sendPushNotification(String title, String message) throws Exception {
        String pushMessage = "{\"data\":{\"title\":\"" +
                title +
                "\",\"message\":\"" +
                message +
                "\"},\"to\":\"" +
                DEVICE_TOKEN +
                "\"}";
        URL url = new URL("https://fcm.googleapis.com/fcm/send");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestProperty("Authorization", "key=" + SERVER_KEY);
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        OutputStream outputStream = conn.getOutputStream();
        outputStream.write(pushMessage.getBytes());
    }
}

И

NotificationProcessing.java

public class NotificationProcessing {

    private static NotificationRepo notificationRepo;

    @Autowired
    public NotificationProcessing(NotificationRepo notificationRepo) {
        NotificationProcessing.notificationRepo = notificationRepo;
    }

    public static void addNotification(Offer offer) throws Exception {
        Notification notification = new Notification();
        notification.setId(null);
        notification.setMessage("There is new offer: " + offer.getTitle());
        notification.setLink("/offers/" + offer.getId());
        notificationRepo.save(notification);

        String[] arguments = new String[] {"New Offer", notification.getMessage()};
        AndroidPush.main(arguments);
    }
}

Я вызываю свой репозиторий внутри статического метода, например Francisco Speath ответил на этот вопрос @ Автосоединение и статический метод

Но тогда, если я попробуючтобы вызвать мой метод и сохранить уведомление, я получаю эту ошибку:

java.lang.NullPointerException: null

в этой строке: notificationRepo.save(notification);

Я полагаю, это потому, что при использовании репозитория внутри статического метода, но если я удаляю статический файл из любого места и пытаюсь получить доступ к методу addNotification (), возникает другая ошибка:

на нестатический метод нельзя ссылаться изстатический контекст

Я вызываю этот метод addNotification () внутри моего RestController

@RequestMapping(method = RequestMethod.POST)
public Offer newOffer (@RequestBody Offer offer) {
    NotificationProcessing.addCampaignNotification(offer);
    return repo.save(offer);
}

Так, каково решение для использования хранилища внутри статического метода?

Ответы [ 3 ]

0 голосов
/ 21 декабря 2018

Упомянутый вопрос описывает, как ссылаться на поле экземпляра, введенное Spring из статического метода.
Поскольку модификаторы static не имеют доступа к полям экземпляра, это может иметь смысл.
Но этоэто не стандарт, это обходной путь для унаследованного кода или библиотек, где кажется сложным или невозможным сделать статический метод экземпляром метода.

Полагаю, это связано с тем, что при использовании репозитория внутри static ethod, но если я удалю static из любого места и попытаюсь получить доступ к методу addNotification (), возникает другая ошибка:

Нестатический метод не может быть вызван из статического контекста.

Вы находитесь на неправильном пути.
Чтобы использовать зависимости bean-компонентов, вам нужно внедрить их туда, где они нужны в других bean-компонентах.
Вы никогда не будете определять методы с модификатором static в bean-компоненте и вызывать его из другого bean-компонента с помощью префикса класса.
Bean-объекты являются экземплярами.Они не связаны с самим классом.

Кроме того, если notificationRepo.save(notification); вызывает исключение NullPointerException, это означает одну вещь: ваш класс не является бобовой пружиной, потому что здесь контекст Spring не будет успешно загружен, если не может быть разрешена зависимость notificationRepo:

@Autowired
public NotificationProcessing(NotificationRepo notificationRepo) {
    NotificationProcessing.notificationRepo = notificationRepo;
}

Короче говоря, аннотируйте свой класс, чтобы он стал Spring Bean, и удалите все эти статические модификаторы:

@Component
public class NotificationProcessing {
    ...
}

И добавьте это таким образом в контроллер:

private NotificationProcessing notificationProcessing;

public MyController(NotificationProcessing notificationProcessing){
  this.notificationProcessing = notificationProcessing;
}

@RequestMapping(method = RequestMethod.POST)
public Offer newOffer (@RequestBody Offer offer) {
    notificationProcessing.addCampaignNotification(offer);
    return repo.save(offer);
}
0 голосов
/ 21 декабря 2018

Я думаю, вы должны изменить NotificationProcessing.addCampaignNotification(offer); на notificationProcessing.addCampaignNotification(offer); и добавить notificationProcessing в свой контроллер, добавив следующий конструктор:

@Autowired
public YourController(NotificationProcessing notificationProcessing) {
    this.notificationProcessing= notificationProcessing;
}
0 голосов
/ 21 декабря 2018

Конструктор вызывается при создании экземпляра вашего объекта, поэтому нелогично пометить конструктор с помощью @Autowired и использовать внедренные экземпляры из статического контекста.Как я вижу, NotificationProcessing не помечен как @Component, поэтому я не уверен, что он вообще обрабатывается контейнером.

Я бы порекомендовал вам удалить модификаторы static из notificationRepoи addNotification(), помечая класс как @Component и вызывая addNotification() из внедренного экземпляра NotificationProcessing.

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