使用Serializable对象中的spring bean

时间:2014-06-27 11:57:01

标签: java spring serialization

我需要在远程机器上执行任务 此任务是虚拟Runnable或Callable和Serializable,可以传输到远程主机,反序列化并在那里执行 我需要使用该任务的spring bean在远程机器上执行它。

什么是优雅的方式来序列化'任务在客户端计算机上序列化时的bean名称和'反序列化'远程机器上的反序列化时真正的bean? 还有其他方法吗?

2 个答案:

答案 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