1

I am upgrading old Java EE application to Spring based solution. In the old applications there were custom annotations to create proxy inject proxy bean and intercept the method invocation [Interceptor classes implements MethodInterceptor) or (implements InvocationHandler), which used to perform some before and after execution stuff.

We have replaced those custom annotations with Spring marker interfaces like @Service, @Repository etc. and we are able to use @Autowire the bean instances. Now my question is how to intercept these autowired beans to perform per and post execution activities. One solution I can think is to use Spring AOP and use @Around pointcut. Just want to know is there any other and better alternative which can be used like

  1. extending org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
  2. Using BeanFactoryPostProcessor or BeanPostProcessor.
  3. Using InstantiationAwareBeanPostProcessor
Debopam
  • 3,198
  • 6
  • 41
  • 72

1 Answers1

0

I have used this alternative instead of AOP. I have used Spring's bean pre & post processor call back. Below is the code snippet.

Application Context Provider, to get Spring beans statically

package com.appname.config;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @author dpoddar
 *
 */
@Component("applicationContextProvider")
public class ApplicationContextProvider implements ApplicationContextAware{
    private static ApplicationContext ctx = null;

    public static ApplicationContext getApplicationContext() {
        return ctx;
    }
    
    @Override
    @Autowired
    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        ApplicationContextProvider.ctx = ctx;
    }
    
    /**
     * Returns the Spring managed bean instance of the given class type if it exists.
     * Returns null otherwise.
     * @param beanClass
     * @return
     */
    public static <T extends Object> T getBean(Class<T> beanClass) {
        return ctx.getBean(beanClass);
    }
    
    /**
     * Returns the Spring managed bean instance of the given class type if it exists.
     *  
     * @param <T>
     * @param name
     * @param beanClass
     * @return
     */
    public static <T extends Object> T getBean(String name,Class<T> beanClass) {
        return ctx.getBean(name,beanClass);
    }

}

Spring Bean Post Processor, InstantiationAwareBeanPostProcessor adds before and after initialization call backs

package com.appname.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.SpringProxy;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import com.appname.core.ExecutionContext;
import com.appname.core.di.FacadeService;
import com.appname.interceptors.BusinesServiceInterceptor;
import com.appname.interceptors.FacadeServiceInterceptor;
import com.appname.interceptors.RepositoryInterceptor;

import net.sf.cglib.proxy.Enhancer;

/**
 * @author dpoddar
 *
 */
@Component
public class AppSpringBeanPostProcessor extends AutowiredAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor  {

    private static Logger logger = LoggerFactory.getLogger(AppSpringBeanPostProcessor.class);

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        Class<?> clazz = bean.getClass();
        AutowireCapableBeanFactory factory = ApplicationContextProvider.getApplicationContext().getAutowireCapableBeanFactory();

        if(clazz.isAnnotationPresent(FacadeService.class)) {
            //This is to instatiate InvocationHandler classes
            //return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new FacadeServiceInterceptor(bean));

            FacadeServiceInterceptor interceptor = new FacadeServiceInterceptor();
            Enhancer e = new Enhancer();
            e.setSuperclass(clazz);
            e.setInterfaces(new Class[]{SpringProxy.class});  /// Identification Spring-generated proxies
            e.setCallback(interceptor);
            Object o = e.create();
            factory.autowireBean( o ); //Autowire Bean dependecies to the newly created object
            return o;

        }else if(clazz.isAnnotationPresent(Service.class)) {
            BusinesServiceInterceptor interceptor = new BusinesServiceInterceptor();
            Enhancer e = new Enhancer();
            e.setSuperclass(clazz);
            e.setInterfaces(new Class[]{SpringProxy.class});
            e.setCallback(interceptor);
            Object o = e.create();
            factory.autowireBean( o );
            return o;
        }else if(clazz.isAnnotationPresent(Repository.class)) {
            ExecutionContext.newInstance();
            RepositoryInterceptor interceptor = new RepositoryInterceptor();
            Enhancer e = new Enhancer();
            e.setSuperclass(clazz);
            e.setInterfaces(new Class[]{SpringProxy.class});
            e.setCallback(interceptor);
            return e.create();
        }else {
            return bean;
        }

    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}
Debopam
  • 3,198
  • 6
  • 41
  • 72