java反射机制运行时动态生成class 和 spring 的bean管理 给代码提供了极大的灵活性,简直到了为所欲为的地步,不建议乱用,这里记录一下平时用到的
一 bytecode方式(例如java assist) 动态生成class ,dubbo里里有源码,有空整理
二 spring容器里动态替换掉运行的类,动态增加bean的 属性。
1. 下面的代码提供运行条件和待测试的bean
1 @Component 2 @Lazy(false) 3 public class SpringUtil implements ApplicationContextAware { 4 5 private static ApplicationContext applicationContext; 6 //获取applicationContext 7 public static ApplicationContext getApplicationContext() { 8 return applicationContext; 9 } 10 11 //通过name获取 Bean. 12 public static Object getBean(String name) { 13 return getApplicationContext().getBean(name); 14 } 15 16 //通过class获取Bean. 17 public static <T> T getBean(Class<T> clazz) { 18 return getApplicationContext().getBean(clazz); 19 } 20 21 //通过name,以及Clazz返回指定的Bean 22 public static <T> T getBean(String name, Class<T> clazz) { 23 return getApplicationContext().getBean(name, clazz); 24 } 25 26 @Override 27 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 28 if (SpringUtil.applicationContext == null) { 29 SpringUtil.applicationContext = applicationContext; 30 } 31 } 32 33 private SpringUtil() { 34 } 35 }
1 public interface BeanTestMe { 2 String getIdentity(); 3 } 4 5 @Service("beanTestMe1") 6 public class BeanTestMe1 implements BeanTestMe{ 7 public String getIdentity(){ 8 return "1"; 9 } 10 } 11 12 @Service("beanTestMe2") 13 public class BeanTestMe2 implements BeanTestMe{ 14 public String getIdentity(){ 15 return "2"; 16 } 17 }
2.下面这个类具体操作bean
1 @Component 2 @Lazy(false) 3 public class InitBeanPropertyConfig implements ApplicationListener<ContextRefreshedEvent> { 4 @Override 5 public void onApplicationEvent(ContextRefreshedEvent event){ 6 if (event.getApplicationContext().getParent() == null) { 7 /** 8 获取beanfactroy等类 9 */ 10 ApplicationContext ac = SpringUtil.getApplicationContext(); 11 DefaultListableBeanFactory fty = (DefaultListableBeanFactory) ac.getAutowireCapableBeanFactory() ; 12 13 /** 14 获取mybFormalClientService,增加dependsOn属性 15 */ 16 BeanDefinition bd = fty.getBeanDefinition("mybFormalClientService"); 17 //fty.getBeanDefinitionNames() 18 String[] dependsOn = bd.getDependsOn(); 19 String[] dependsOnNew; 20 if (dependsOn == null || dependsOn.length == 0){ 21 dependsOnNew = new String[1]; 22 dependsOnNew[0] = "mwMaskConvertHelper"; 23 }else{ 24 dependsOnNew = new String[dependsOn.length + 1]; 25 System.arraycopy(dependsOn,0,dependsOnNew,0,dependsOn.length); 26 dependsOnNew[dependsOnNew.length-1] = "mwMaskConvertHelper"; 27 } 28 bd.setDependsOn(dependsOnNew); 29 fty.registerBeanDefinition("mybFormalClientService", bd); 30 31 /** 32 动态获取到beanTestMe1,把执行类换成BeanTestMe2,注册,然后再次执行结果是BeanTestMe2 的结果 33 */ 34 bd = fty.getBeanDefinition("beanTestMe1"); 35 ((BeanTestMe)fty.getBean("beanTestMe1")).getIdentity(); 36 bd.setBeanClassName("com.ymm.crm.biz.BeanTestMe2"); 37 fty.registerBeanDefinition("beanTestMe1", bd); 38 ((BeanTestMe)fty.getBean("beanTestMe1")).getIdentity(); 39 } 40 } 41 }
三 继承spring 的 FactoryBean 动态生成bean, 服务注册Pegion 源码里使用到了。