如何将Swing JFrame配置为Spring bean?

时间:2011-09-21 16:16:34

标签: java spring swing

我有一个简单的JFrame作为我的Java桌面应用程序的主窗口,我想将它配置为Spring bean。我想设置属性,注入依赖项并启动它。这是我的框架类:

public class MainFrame extends JFrame {
    public MainFrame() {
        setTitle("Static Title");
        setVisible(true);
    }
}

My Spring应用程序上下文:

<bean class="com.example.MainFrame">
    <property name="title" value="Injected Title" />
</bean>

然后我把它全部解开......

public static void main(String ... args) {
    new ClassPathXmlApplicationContext("applicationContext.xml");
}

...后跟java.beans.IntrospectionException

type mismatch between indexed and non-indexed methods: location

实际显示的是框架,但是存在异常,标题仍为“静态标题”。所以我有几个问题......

我已经看到这是done by IBM in a 2005 tutorial但是使用Spring 1.2,我甚至不知道什么是JRE。那么我该如何处理这个异常呢?是否可以将JFrame配置为Spring bean,还是需要代理它或什么?

我也担心不从事件调度线程启动应用程序。所以,如果有一个更清洁的方式,我想知道它。除了我不知道如何派遣建筑本身之外,我可以轻松地派遣所有东西。

最后随意批评整体概念。我没有遇到很多Spring管理的Swing应用程序的例子。我正在使用带有Java-1.6的Spring-3.1。

感谢。

4 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,而且看起来它实际上是Spring上的一个错误: https://jira.springsource.org/browse/SPR-8491

我想我会在面板周围打一个FactoryBean,看它是否有效。我稍后会编辑这篇文章,以防它有效(或没有)

- 编辑 -

好的,通过FactoryBean实例化它可以解决问题。声明变得有点尴尬,但这必须要做,至少在上述错误修复之前。

package com.ats.jnfe.swing;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.FactoryBean;

/**
 * Contorna, em caráter temporário, o bug apontado em:
 * https://jira.springsource.org/browse/SPR-8491
 * Quando o erro acima for resolvido, esta classe estará obsoleta.
 *
 * @author HaroldoOliveira
 */
public class SwingFactoryBean<T> implements FactoryBean<T> {

    private Class<T> beanClass;
    private Map<String, Object> injection;
    private String initMethod;

    private Map<String, PropertyDescriptor> properties;
    private BeanInfo beanInfo;
    private Method initMethodRef;

    public T getObject() throws Exception {
    T t = this.getBeanClass().newInstance();

    if (this.getInjection() != null) {
        for (Map.Entry<String, Object> en : this.getInjection().entrySet()) {
        try {
            this.properties.get(en.getKey()).getWriteMethod()
                .invoke(t, en.getValue());
        } catch (Exception e) {
            throw new BeanInitializationException(MessageFormat.format(
                "Error initializing property {0} of class {1}",
                en.getKey(), this.getBeanClass().getName()), e);
        }
        }
    }

    if (this.initMethodRef != null) {
        this.initMethodRef.invoke(t);
    }

    return t;
    }

    public Class<?> getObjectType() {
    return this.getBeanClass();
    }

    public boolean isSingleton() {
    return false;
    }

    public void initialize() {
    try {
        this.beanInfo = Introspector.getBeanInfo(this.getBeanClass());
        this.properties = new HashMap<String, PropertyDescriptor>();

        PropertyDescriptor[] descriptors = this.beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor pd : descriptors) {
        this.properties.put(pd.getName(), pd);
        }

        if (this.getInitMethod() != null) {
        this.initMethodRef = this.getBeanClass()
            .getMethod(this.getInitMethod());
        }
    } catch (Exception e) {
        throw new BeanInitializationException(
            "Error initializing SwingFactoryBean: " + e.getMessage(), e);
    }
    }

    public Class<T> getBeanClass() {
    if (this.beanClass == null) {
        throw new BeanInitializationException("Class not informed.");
    }
    return this.beanClass;
    }
    public void setBeanClass(Class<T> beanClass) {
    this.beanClass = beanClass;
    }

    public Map<String, Object> getInjection() {
    return injection;
    }
    public void setInjection(Map<String, Object> injection) {
    this.injection = injection;
    }

    public String getInitMethod() {
    return initMethod;
    }
    public void setInitMethod(String initMethod) {
    this.initMethod = initMethod;
    }

}

用法示例:

<bean id="certificadoNFeConfiguracaoDialog" class="com.ats.jnfe.swing.SwingFactoryBean" init-method="initialize" scope="prototype" lazy-init="true">
<property name="beanClass" value="com.ats.ecf.view.swing.util.dialog.OKCancelDialog" />
<property name="initMethod" value="inicializa" />
<property name="injection">
    <map>
    <entry key="selector">
        <bean class="com.ats.jnfe.swing.SwingFactoryBean" init-method="initialize">
        <property name="beanClass" value="com.ats.jnfe.swing.CertificadoNFeConfigPanel" />
        <property name="initMethod" value="inicializa" />
        <property name="injection">
            <map>
            <entry key="fachada" value-ref="certificadoNFeConfiguracaoFacade" />
            </map>
        </property>
        </bean>
    </entry>
    </map>
</property>
</bean>

答案 1 :(得分:1)

使用Spring 3.0.7.RELEASE,3.1.4.RELEASE和3.2.3.RELEASE运行。

这似乎是另一个答案中提到的错误。

答案 2 :(得分:0)

我的想法是让Swing脱离春天。过去任何微不足道的事情,使用别的东西连接GUI都会变得太乏味。相反,我会改变你正在做的事情,只需使用main()来创建Spring内容,然后创建你的GUI。

如果您在Spring中所做的一切都是创建MainFrame并启动它,那么最简单的方法就是创建一个创建框架的FactoryBean。工厂也可以通过setVisible()来电拨打SwingUtilities.invokeLater()

答案 3 :(得分:0)

使用Spring 4.0.2.RELEASE确认运行。