java - 使用可序列化对象中的 spring bean

标签 java spring serialization

我需要在远程计算机上执行任务。
该任务是虚拟的可运行或可调用且可序列化,将传输到远程主机,在那里反序列化并执行。
我需要使用该任务中的 spring bean 在远程计算机上执行它。

在客户端机器上序列化任务时“序列化”bean 名称以及在远程机器上反序列化时“反序列化”真实 bean 的优雅方式是什么?
还有其他解决方案吗?

最佳答案

    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);
        }
    }

关于java - 使用可序列化对象中的 spring bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24451257/

相关文章:

java - 从 Felix 获取具体实现

java - Spring - 为什么不使用 log4j2 XML 配置文件?

c++ - 序列化与文件加载

spring - 从 BundleContextAware 类访问应用程序上下文

C# 使用 JavaScriptSerializer.DeserializeObject 反序列化 JSON

python - 如何序列化 beautifulsoup 访问路径?

java - 垃圾收集器不会立即收集完成的线程

java - 如何检测另一个java线程是否被挂起或卡住?

java - 无法捕获 JsonMappingException

java - 将 ConstraintValidator 实现注册到 Constraint