我需要在远程机器上执行任务 此任务是虚拟Runnable或Callable和Serializable,可以传输到远程主机,反序列化并在那里执行 我需要使用该任务的spring bean在远程机器上执行它。
什么是优雅的方式来序列化'任务在客户端计算机上序列化时的bean名称和'反序列化'远程机器上的反序列化时真正的bean? 还有其他方法吗?
答案 0 :(得分:1)
private static class MyCommand implements Callable<String>, Serializable {
private static final long serialVersionUID = 8980820796677215627L;
private transient SpringBean springBean;
private String bar;
public InitDoneRemoteCommand(SpringBean springBean, String bar) {
this.springBean = springBean;
this.bar = bar;
}
@Override
public String call() {
return springBean.foo(bar);
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(getBeanName(springBean));
}
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
springBean = getBean((String) in.readObject());
}
}
SpringContext .java
@Resource
public class SpringContext implements ApplicationContextAware, BeanPostProcessor, BundleContextAware, ServiceListener {
private static ApplicationContext applicationContext;
private static BundleContext bundleContext;
private static Map<Object, String> springBeanToName = synchronizedMap(new WeakHashMap<Object, String>());
private static Map<String, ServiceReference> osgiNameToServiceReference = synchronizedMap(new WeakHashMap<String, ServiceReference>());
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static BundleContext getBundleContext() {
return bundleContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
ServiceReference ref = osgiNameToServiceReference.get(name);
if (ref != null)
return (T) bundleContext.getService(ref);
return (T) applicationContext.getBean(name);
}
public static String getBeanName(Object bean) {
if (isOsgiBean(bean))
return getOsgiBeanName(bean);
return springBeanToName.get(bean);
}
public static boolean isOsgiBean(Object bean) {
return bean instanceof ImportedOsgiServiceProxy || bean instanceof ServiceReferenceProxy || bean instanceof ServiceReference;
}
public static String getOsgiBeanName(Object proxy) {
if (proxy == null)
return null;
ServiceReference serviceReference = null;
if (proxy instanceof ImportedOsgiServiceProxy)
serviceReference = ((ImportedOsgiServiceProxy) proxy).getServiceReference().getTargetServiceReference();
else if (proxy instanceof ServiceReferenceProxy)
serviceReference = ((ServiceReferenceProxy) proxy).getTargetServiceReference();
else if (proxy instanceof ServiceReference)
serviceReference = ((ServiceReference) proxy);
if (serviceReference != null)
return (String) serviceReference.getProperty(OSGI_BEAN_NAME_PROPERTY);
throw new IllegalArgumentException(proxy.toString());
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
springBeanToName.put(bean, beanName);
return bean;
}
@Override
public void serviceChanged(ServiceEvent event) {
ServiceReference ref = event.getServiceReference();
String name = getOsgiBeanName(ref);
if (event.getType() == ServiceEvent.REGISTERED)
osgiNameToServiceReference.put(name, ref);
else if (event.getType() == ServiceEvent.UNREGISTERING)
osgiNameToServiceReference.remove(name);
}
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
SpringContext.applicationContext = context;
}
@Override
public void setBundleContext(BundleContext bundleContext) {
SpringContext.bundleContext = bundleContext;
bundleContext.addServiceListener(this);
}
}
答案 1 :(得分:0)
如果您有权访问ApplicationContext,您可以要求它为您创建实例,例如启用自动装配:
appContext.getAutowireCapableBeanFactory().createBean(
beanClass,
AbstractBeanDefinition.AUTOWIRE_BY_TYPE,
true)
更优雅的方法是使用@Configurable注释类,描述为here。