Почему Springboot обновляет компонент только один раз, когда я удаляю компонент и добавляю еще один компонент? - PullRequest
0 голосов
/ 05 июля 2019

У меня есть требование удалить соответствующий Бин и затем добавить другой Бин, но я считаю, что Springboot обновляет введенный Бин только один раз

версия для Springboot - 2.1.5. RELEASE, JDK1.8

    public class Users {
        String name;
        int age;
        String gender;

        public Users() {
        }
        public Users(String name, int age, String gender) {
            this.name = name;
            this.age = age;
            this.gender = gender;
        }
    }
    @Component
    public class UsersController implements ApplicationRunner {
         @Autowired(required = false)
    //     @Resource
         List<Users> users= Collections.emptyList();


        @Override
        public void run(ApplicationArguments args) {
            System.out.println(users);
        }
    }
    @RestController
    public class HelloController implements 
    BeanDefinitionRegistryPostProcessor, ApplicationContextAware {

        ApplicationContext applicationContext;

        DefaultListableBeanFactory defaultListableBeanFactory;

        Users users;

        int i=0;

        @RequestMapping("/hello1")
        public String index1() {
            return "hello";
        }
        @RequestMapping("/hello3")
        public Users index3() {
            UsersController controller = 
    applicationContext.getBean(UsersController.class);
            controller.run(null);
            return null;
        }

        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry 
    registry) throws BeansException {

        }

        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory 
    beanFactory) throws BeansException {
            defaultListableBeanFactory= (DefaultListableBeanFactory) 
    beanFactory;
            Users users=new Users("hello"+(i++),23,"fe");
            this.users=users;
            defaultListableBeanFactory.registerBeanDefinition(users.getName(),
                BeanDefinitionBuilder.genericBeanDefinition(Users.class, () -> 
    users).getRawBeanDefinition());

        }
        @EventListener
        public void onApplicationEvent(@NonNull EnvironmentChangeEvent 
    environmentChangeEvent) {
            System.out.println("before 
    remove:"+applicationContext.getBean(Users.class));
            defaultListableBeanFactory.removeBeanDefinition(users.getName());
            Users users=new Users("hello"+(i++),23,"fe");
            this.users=users;
            defaultListableBeanFactory.registerBeanDefinition(users.getName(),
                    BeanDefinitionBuilder.genericBeanDefinition(Users.class, 
    () -> users).getRawBeanDefinition());

        System.out.println("after:"+applicationContext.getBean(Users.class));
        }

        @Override
        public void setApplicationContext(ApplicationContext 
    applicationContext) throws BeansException {
            this.applicationContext=applicationContext;
        }
    }

pom.xml:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
         </dependency>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
            <version>RELEASE</version>
         </dependency>
         <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
             <version>1.18.8</version>
          </dependency>
    </dependencies>

только bootstrap.yml:

     management:
      endpoints:
        web:
          exposure:
           include: '*'
      endpoint:
        health:
          show-details: always

при запуске приложения оно выдаст
[Users(name=hello0, age=23, gender=fe)],
а затем посетите URL по почте,
http://localhost:8080/actuator/refresh
это будет выводить
before remove:Users(name=hello0, age=23, gender=fe)
after:Users(name=hello1, age=23, gender=fe)
затем посетите URL
http://localhost:8080/hello3
выход
[Users(name=hello1, age=23, gender=fe)]
Этого следовало ожидать, если посетить URL еще раз
http://localhost:8080/actuator/refresh
выход
before remove:Users(name=hello1, age=23, gender=fe)
after:Users(name=hello2, age=23, gender=fe)
Этого также следовало ожидать, но посетите URL
http://localhost:8080/hello3
мы надеемся, что выходной
Users(name=hello2, age=23, gender=fe)
но это вывод
Users(name=hello1, age=23, gender=fe)

Выходное сообщение не соответствует ожиданиям.
Если изменить @Autowired на @Resource в классе UsersController, оно должно быть нормальным. Но в реальной среде это может быть ноль, приложение будет работать неуспешно, если использовать @Resource
Как я могу решить эту проблему?
Спасибо за ваше время.

Ответы [ 2 ]

0 голосов
/ 11 июля 2019

Пожалуйста, посмотрите на эту часть документации, чтобы обновить ваши bean-компоненты во время выполнения: https://cloud.spring.io/spring-cloud-static/Greenwich.SR1/single/spring-cloud.html#refresh-scope

0 голосов
/ 05 июля 2019

@ ресурсы @Lazy Может помечать приложение правильно. Но это может привести к ошибке, как
ERROR [main] com.Users - No qualifying bean of type 'java.util.List<com.Users>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=), @org.springframework.context.annotation.Lazy(value=true)}

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