今晚翻看了以前写的RPC框架。发现这个框架中编程式配置Spring bean的技巧还是比较通用的,其他的一些框架或基础服务可能也会用到。记得当时也是从Struts2的代码里找到的,在此先做下记录,以供以后参考。
使用方式:
1.上面的RpcMethodHelper本身也应该配置到spring容器中
2.如果不想将上面的类配置为Spring bean,那只要在工具类中得到ApplicationContext的引用即可。
public class RpcMethodHelper implements ApplicationContextAware {
protected static final Logger logger = LoggerFactory.getLogger(RpcMethodHelper.class);
protected ApplicationContext appContext;
protected AutowireCapableBeanFactory autoWiringFactory;
protected int autowireStrategy = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
/**
* 初始化Action如果已经在spring中注册过则从spring容器中得到Action实例, 如果spring容器中没有注册则先注册并返回实例
* 返回的Action实例已经注入了依赖的其他对象及请求参数
*
* @param <T>
* @param clazz
* @return
*/
protected <T> T createAction(Class<T> clazz) {
T action = null;
String beanName = clazz.getName();
try {
logger.debug("Trying the application context... appContext = {},\n bean name = {}" ,appContext,beanName);
action = clazz.cast(appContext.getBean(beanName));//先从spring容器中得到bean
} catch (NoSuchBeanDefinitionException e) {
//如果spring容器中没有注册则先注册并返回实例
logger.debug("Did not find bean definition for bean named {}, creating a new one...",beanName);
if (autoWiringFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) autoWiringFactory;
RootBeanDefinition def = new RootBeanDefinition(clazz,
autowireStrategy);//设置autowire策略,根据具体应用来决定
// def.setSingleton(false);
def.setScope("prototype");//这里的scope类型可以根据需要设置
logger.debug("Registering a new bean definition for class "
+ beanName);
registry.registerBeanDefinition(beanName, def);
try {
action = clazz.cast(appContext.getBean(beanName));
} catch (NoSuchBeanDefinitionException e2) {
logger.warn("Could not register new bean definition for bean {}"
,beanName);
}
}
}
return action;
}
public void setApplicationContext(ApplicationContext context)
throws BeansException {
appContext = context;
autoWiringFactory = findAutoWiringBeanFactory(this.appContext);
}
/**
*
* @see com.opensymphony.xwork2.spring.SpringObjectFactory#findAutoWiringBeanFactory
* @param context
*/
protected AutowireCapableBeanFactory findAutoWiringBeanFactory(
ApplicationContext context) {
if (context instanceof AutowireCapableBeanFactory) {
// Check the context
return (AutowireCapableBeanFactory) context;
} else if (context instanceof ConfigurableApplicationContext) {
// Try and grab the beanFactory
return ((ConfigurableApplicationContext) context).getBeanFactory();
} else if (context.getParent() != null) {
// And if all else fails, try again with the parent context
return findAutoWiringBeanFactory(context.getParent());
}
return null;
}
/**
* Sets the autowiring strategy
*
* @see com.opensymphony.xwork2.spring.SpringObjectFactory#setAutowireStrategy
* @param autowireStrategy
*/
public void setAutowireStrategy(int autowireStrategy) {
switch (autowireStrategy) {
case AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT:
logger.info("Setting autowire strategy to autodetect");
this.autowireStrategy = autowireStrategy;
break;
case AutowireCapableBeanFactory.AUTOWIRE_BY_NAME:
logger.info("Setting autowire strategy to name");
this.autowireStrategy = autowireStrategy;
break;
case AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE:
logger.info("Setting autowire strategy to type");
this.autowireStrategy = autowireStrategy;
break;
case AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR:
logger.info("Setting autowire strategy to constructor");
this.autowireStrategy = autowireStrategy;
break;
default:
throw new IllegalStateException("Invalid autowire type set");
}
}
}
使用方式:
1.上面的RpcMethodHelper本身也应该配置到spring容器中
<bean id="rpcMethodHelper" class="com.niagara.rpc.RpcMethodHelper"></bean>
2.如果不想将上面的类配置为Spring bean,那只要在工具类中得到ApplicationContext的引用即可。