0

This method is first checked by beanDefintirions for the original Beans (Configureablelistablebeanfactory beanFactory is used; ).

ConfigurableListableBeanFactory beanFactory; injected.

Then all the methods of the original bean, which was obtained from the BeanFactory, are iterated over. After searching over the methods of a certain annotation, we get the Bean from the Applicationcontext.

This Bean is a proxy wrapper over the original Bean, which was formed at the - > postProcessBeforeInitialization() stage. Now through this bean, I call a method that has been marked with the annotation I need, but it requires another argument Obj ..args.

How do I get the missing argument ?

Использую Srping 5.x, java 11

private void runMethodWithPostProxyThirdPhaseAnnotation(String beanName, ApplicationContext applicationContext) {

      BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);


      try {
          String originalBeanClassName = beanDefinition.getBeanClassName();

          if (originalBeanClassName != null) {
              Class<?> originalClass = Class.forName(originalBeanClassName);
              Method[] methods = originalClass.getMethods();

              for (Method method : methods) {
                  if (method.isAnnotationPresent(PostProxyThirdPhase.class)) {
                      

                      String originalMethodName = method.getName();
                      Class<?>[] parameterTypesFromOriginalMethod = method.getParameterTypes();

                      Object beanAfterProxy = applicationContext.getBean(beanName);

                      Method methodFromProxyBean = beanAfterProxy
                              .getClass()
                              .getMethod(originalMethodName, parameterTypesFromOriginalMethod);

                      methodFromProxyBean.invoke(beanAfterProxy, ?);
                  }
              }
          }

      } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
          e.printStackTrace();
      }

}

1 Answer 1

1

Solution


three-phase constructor (implementation).

The answer was in the documentation for the method :

  • public Object invoke(Object obj, Object... args)

@param args the arguments used for the method call


import bean.post.process.annotation.PostProxyThirdPhase;
import bean.post.process.bean.Quoter;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

@Component
public class PostProxyInvokerContextListener implements ApplicationListener<ContextRefreshedEvent> {

    private final ConfigurableListableBeanFactory beanFactory;

    private final Quoter quoter;

    public PostProxyInvokerContextListener(ConfigurableListableBeanFactory beanFactory, Quoter quoter) {
        this.beanFactory = beanFactory;
        this.quoter = quoter;
    }


    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        ApplicationContext applicationContext = event.getApplicationContext();

        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();

        Arrays.stream(beanDefinitionNames)
                .forEach(beanName -> runMethodWithPostProxyThirdPhaseAnnotation(beanName, applicationContext));
    }


    private void runMethodWithPostProxyThirdPhaseAnnotation(String beanName, ApplicationContext applicationContext) {

        BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);

        try {
            String originalBeanClassName = beanDefinition.getBeanClassName();

            if (originalBeanClassName != null) {
                Class<?> originalClass = Class.forName(originalBeanClassName);
                Method[] methods = originalClass.getMethods();

                for (Method method : methods) {
                    if (method.isAnnotationPresent(PostProxyThirdPhase.class)) {

                        String originalMethodName = method.getName();
                        Class<?>[] parameterTypesFromOriginalMethod = method.getParameterTypes();

                        Object beanAfterProxy = applicationContext.getBean(beanName);

                        Method methodFromProxyBean = beanAfterProxy
                                .getClass()
                                .getMethod(originalMethodName, parameterTypesFromOriginalMethod);

                        Object[] args = new Object[]{quoter};

                        methodFromProxyBean.invoke(beanAfterProxy, args);
                    }
                }
            }

        } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.