All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.example.beaninitself.code.AsyncProxyBeanPostProcessor Maven / Gradle / Ivy

package com.example.beaninitself.code;

import java.lang.reflect.Method;
import java.util.concurrent.CountDownLatch;

import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.AbstractApplicationContext;

import org.springframework.core.PriorityOrdered;

/**
 * @author qilong.zql
 * @author xuanbei
 * @since 2.6.0
 */
@Slf4j
public class AsyncProxyBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware,
        InitializingBean, PriorityOrdered {

    private ApplicationContext applicationContext;

    private String             moduleName = "whymax";

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        String methodName = AsyncInitBeanHolder.getAsyncInitMethodName(moduleName, beanName);
        if (methodName == null || methodName.length() == 0) {
            return bean;
        }

        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTargetClass(bean.getClass());
        proxyFactory.setProxyTargetClass(true);
        AsyncInitializeBeanMethodInvoker asyncInitializeBeanMethodInvoker = new AsyncInitializeBeanMethodInvoker(
                bean, beanName, methodName);
        proxyFactory.addAdvice(asyncInitializeBeanMethodInvoker);
        return proxyFactory.getProxy();
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        return bean;
    }

    @Override
    public void afterPropertiesSet() {
//        ConfigurableBeanFactory beanFactory = ((AbstractApplicationContext) applicationContext)
//                .getBeanFactory();
//        if (beanFactory instanceof BeanLoadCostBeanFactory) {
//            moduleName = ((BeanLoadCostBeanFactory) beanFactory).getId();
//        } else {
//            moduleName = SofaBootConstants.ROOT_APPLICATION_CONTEXT;
//        }
    }

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

    @Override
    public int getOrder() {
        return PriorityOrdered.HIGHEST_PRECEDENCE;
    }

    class AsyncInitializeBeanMethodInvoker implements MethodInterceptor {
        private final Object         targetObject;
        private final String         asyncMethodName;
        private final String         beanName;
        private final CountDownLatch initCountDownLatch = new CountDownLatch(1);
        // mark async-init method is during first invocation.
        private volatile boolean     isAsyncCalling     = false;
        // mark init-method is called.
        private volatile boolean     isAsyncCalled      = false;

        AsyncInitializeBeanMethodInvoker(Object targetObject, String beanName, String methodName) {
            this.targetObject = targetObject;
            this.beanName = beanName;
            this.asyncMethodName = methodName;
        }

        @Override
        public Object invoke(final MethodInvocation invocation) throws Throwable {
            // if the spring refreshing is finished
            if (AsyncTaskExecutor.isStarted()) {
                return invocation.getMethod().invoke(targetObject, invocation.getArguments());
            }

            Method method = invocation.getMethod();
            final String methodName = method.getName();
            if (!isAsyncCalled && methodName.equals(asyncMethodName)) {
                isAsyncCalled = true;
                isAsyncCalling = true;
                AsyncTaskExecutor.submitTask(applicationContext.getEnvironment(), new Runnable() {
                    @Override
                    public void run() {
                        try {
                            long startTime = System.currentTimeMillis();
                            invocation.getMethod().invoke(targetObject, invocation.getArguments());
                            log.info(String.format(
                                    "%s(%s) %s method execute %dms, moduleName: %s.", targetObject
                                            .getClass().getName(), beanName, methodName, (System
                                            .currentTimeMillis() - startTime), moduleName));
                        } catch (Throwable e) {
                            throw new RuntimeException(e);
                        } finally {
                            initCountDownLatch.countDown();
                            isAsyncCalling = false;
                        }
                    }
                });
                return null;
            }

            if (isAsyncCalling) {
                long startTime = System.currentTimeMillis();
                initCountDownLatch.await();
                log.info(String.format("%s(%s) %s method wait %dms, moduleName: %s.",
                        targetObject.getClass().getName(), beanName, methodName,
                        (System.currentTimeMillis() - startTime), moduleName));
            }
            return invocation.getMethod().invoke(targetObject, invocation.getArguments());
        }
    }

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy