package org.hotswap.agent.plugin.spring.getbean; import org.hotswap.agent.annotation.OnClassLoadEvent; import org.hotswap.agent.javassist.CannotCompileException; import org.hotswap.agent.javassist.CtClass; import org.hotswap.agent.javassist.CtConstructor; import org.hotswap.agent.javassist.CtMethod; import org.hotswap.agent.javassist.NotFoundException; /** * Transforms Spring classes so the beans go through this plugin. The returned beans are proxied and tracked. The bean * proxies can be reset and reloaded from Spring. * * @author Erki Ehtla * */ public class ProxyReplacerTransformer { public static final String FACTORY_METHOD_NAME = "getBean"; /** * * @param ctClass * @throws NotFoundException * @throws CannotCompileException */ @OnClassLoadEvent(classNameRegexp = "org.springframework.beans.factory.support.DefaultListableBeanFactory") public static void replaceBeanWithProxy(CtClass ctClass) throws NotFoundException, CannotCompileException { CtMethod[] methods = ctClass.getMethods(); for (CtMethod ctMethod : methods) { if (!ctMethod.getName().equals(FACTORY_METHOD_NAME)) continue; StringBuilder methodParamTypes = new StringBuilder(); for (CtClass type : ctMethod.getParameterTypes()) { methodParamTypes.append(type.getName()).append(".class").append(", "); } ctMethod.insertAfter("if(true){return org.hotswap.agent.plugin.spring.getbean.ProxyReplacer.register($0, $_,new Class[]{" + methodParamTypes.substring(0, methodParamTypes.length() - 2) + "}, $args);}"); } } /** * Disable cache usage in FastClass.Generator to avoid 'IllegalArgumentException: Protected method' exceptions * * @param ctClass * @throws NotFoundException * @throws CannotCompileException */ @OnClassLoadEvent(classNameRegexp = "org.springframework.cglib.reflect.FastClass.Generator") public static void replaceSpringFastClassGenerator(CtClass ctClass) throws NotFoundException, CannotCompileException { CtConstructor[] constructors = ctClass.getConstructors(); for (CtConstructor ctConstructor : constructors) { ctConstructor.insertAfter("setUseCache(false);"); } } /** * Disable cache usage in FastClass.Generator to avoid 'IllegalArgumentException: Protected method' exceptions * * @param ctClass * @throws NotFoundException * @throws CannotCompileException */ @OnClassLoadEvent(classNameRegexp = "net.sf.cglib.reflect.FastClass.Generator") public static void replaceCglibFastClassGenerator(CtClass ctClass) throws NotFoundException, CannotCompileException { CtConstructor[] constructors = ctClass.getConstructors(); for (CtConstructor ctConstructor : constructors) { ctConstructor.insertAfter("setUseCache(false);"); } } }