Spring 应用

来源:互联网 发布:公共服务质量数据规范 编辑:程序博客网 时间:2024/05/22 20:49

什么是 Spring 框架?
Spring 框架 Web 站点一般都使用下面的描述来欢迎访问者:“As the leading full-stack Java/J2EE application framework, Spring delivers significant benefits for many projects, reducing development effort and costs while improving test coverage and quality”!
简单来说,Spring 提供了很多工具和方法来简化 Java 和 J2EE 应用程序的编写和测试。

什么是依赖注入?
依赖注入(Dependency Injection,DI),也称为反转控制(Inversion of Control,IOC),是一种进行软件开发的方法,其中由单独的对象或框架(例如 Spring 框架)负责将对象创建或“注入”到依赖于这些对象的其他对象中。这样可以让代码是松耦合的,易于测试和重用。


创建 to-do 列表:基本的 Swing 和 Spring 应用程序设置
1,创建 MainFrame、Launcher 和 ToDo 类
要使用 Swing 应用程序的基本框架,需要以下三部分内容:
a,一个继承 Swing JFrame 类的子类。所有的 Swing 应用程序都有一个主要的外部框架来包含所有其他组件。我们称这个类为 MainFrame。
b,一个 Launcher 类,负责对 Swing 框架进行初始化和配置。
c,一个具有 main 方法的类,用来启动应用程序。我们称这个类为 ToDo。

可以将这三个单独的类组合为一个或二个类,但是将它们作为单独的类实现更简单。将它们作为单独的类在较复杂的应用程序中可以发挥更大的优势。例如,在测试过程中,可能会希望使用一个专用的 Launcher 类,可以从测试中对其进行配置或直接调用 —— 这可以避免普通应用程序启动任务与测试任务之间的不同步,从而不妨碍测试。

MainFrame 类是 Swing JFrame 的一个非常简单直观的实现。配置并显示这个框架的代码是在 public void init() 方法中定义的。这个方法是 Spring 在应用程序中调用的第一个方法,也是 Swing 应用程序的入口。下面是它的清单列表:

package todo.ui;
import java.awt.Dimension;
import java.awt.Frame;
import javax.swing.JFrame;
import javax.swing.WindowConstants;

@SuppressWarnings("serial")
public class MainFrame extends JFrame {
    public void init() {
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        setSize(new Dimension(600, 400));
        setVisible(true);
        setState(Frame.NORMAL);
        pack();
    }
}


Launcher 类的目的是初始化并启动 Spring 框架,这是通过创建一个 ApplicationContext 并向其传递一个包含到 bean 定义文件的路径的数组实现的。在这个框架启动时,Spring 会自动创建 MainFrame 类,因为这个 bean 会定义为一个 Singleton。除了 ClassPathXmlApplicationContext 之外,还有其他几种类型的 ApplicationContext 实现,但是所有的实现都可以作为一种为 Spring 应用程序提供配置的方法。清看它的清单:

package todo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Launcher {
    public void launch() {
        String[] contextPaths = new String[] {"todo/app-context.xml"};
        new ClassPathXmlApplicationContext(contextPaths);
    }
}

ToDo 类非常简单,只有一个 main 方法,它创建了一个 Launcher 实例,并对其调用 launch() 方法,清单如下:

package todo;
public class ToDo {
    public static void main(String[] args) {
        Launcher launcher = new Launcher();
        launcher.launch();
    }
}

 

创建 Spring app-context.xml bean 定义文件:src/todo/app-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
          "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="mainFrame" class="todo.ui.MainFrame" init-method="init">
</bean>
</beans>

这个 bean 定义文件的根元素是 <beans>,它包括 <bean> 元素。<bean> 元素提供了 很多属性,但是对于第一个 bean 定义来说,我们只使用以下三个属性:id、class 和 init-method。id 属性定义了 bean 的名字,这用来从 Spring 中进行检索。class 属性告诉 Spring 在创建这个 bean 时要对哪个类进行实例化。init-method 属性定义了该类的一个方法名,在 Spring 对该类进行实例化之后,会自动调用这个方法。

重要的是要知道所有的 bean 缺省都是 Singleton,除非指定 bean 元素的 singleton="false" 属性。Spring 会在第一次对其进行初始化时自动对所有的 Singleton 进行实例化,除非指定了 lazy-init="true" 属性。

这种自动创建 Singleton 的特性就是 Launcher 类只需要创建 ApplicationContext 而不需要做其他事情的原因。Spring 简单地将 MainFrame 作为一个 Singleton 进行创建,并调用它的 init() 方法,这会让它自己进行显示。

此时运行应用程序时,会看到一个白板,显示一个灰色的界面,上面没有标题!

定义 bean 属性
<bean id="mainFrame" class="todo.ui.MainFrame" init-method="init">
    <property name="title">
      <value>标题</value>
    </property>
</bean>

此时运行应用程序,您应该看到这个框架的标题是 "标题"!

这是对依赖注入性技术的第一次简单应用。您将一个普通的 String 对象插入了 MainFrame 类的 title 属性中。在幕后,Spring 会自动创建一个 String,其值为 “标题”,并将其作为一个参数传递给 todo.ui.MainFrame 类的 setTitle() 方法。这是一个非常重要的概念,由于 Spring 中其他类型的依赖注入基本上都是相同的。可以使用 bean 定义文件来定义值、对象或属性集合,它们可以作为属性传递(注入)到其他对象中。然后,Spring 会在运行时综合应用这些内容,处理对象的创建和属性的设置。

创建 to-do 列表:创建一个可重用组件并在表中显示数据
创建一个可重用的面板,清单如下:
package todo.ui;
import java.awt.Component;
import java.util.Iterator;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class BoxLayoutPanel extends JPanel {
  /**
     * We can't use "components" as the property name,
     * because it conflicts with an existing property
     * on the Component superclass.
     */
    @SuppressWarnings("unchecked")
private List panelComponents;
    private int axis;
    public void setAxis(int axis) {
        this.axis = axis;
    }
    @SuppressWarnings("unchecked")
public void setPanelComponents(List panelComponents) {
        this.panelComponents = panelComponents;
    }
    @SuppressWarnings("unchecked")
public void init() {
        setLayout(new BoxLayout(this, axis));

        for (Iterator iter = panelComponents.iterator();
             iter.hasNext();) {
            Component component = (Component) iter.next();
            add(component);
        }
    }
}

将 bean 组合在一起
<bean id="mainFrame" class="todo.ui.MainFrame" init-method="init">
    <property name="contentPane">
      <ref bean="mainPanel"/>
    </property>
    <property name="title">
      <value>标题</value>
    </property>
</bean>
<bean id="mainPanel" class=
     "todo.ui.BoxLayoutPanel" init-method="init">
    <property name="axis">
      <!-- "1" corresponds to BoxLayout.Y_AXIS -->
      <!-- Spring can access constants, but it's more complex -->
      <value>1</value>
    </property>
    <property name="panelComponents">
      <list>
        <ref bean="itemScrollPane"/>
      </list>
    </property>
</bean>
<bean id="itemScrollPane" class="javax.swing.JScrollPane">
</bean>

首先,创建了一个 mainPanel bean,它与 mainFrame bean 非常类似。然后,将其注入 到 mainFrame bean 中,这是使用 contentPane 属性和 <ref bean="mainPanel"/> 实现的。setContentPane() 是一个将面板添加到框架中的方法。可以自动使用这个方法,因为 MainFrame 是 JFrame 的一个子类,因此就继承了 setContentPane() 方法。<ref bean="mainPanel"/> 简单地利用 Spring 所创建的 mainPanel 对象,并将其传递给 MainPanel 的 setContentPane() 方法。
还给 BoxLayoutPanel 的 axis 和 panelComponents 属性注入了值。对于 axis 来说,1 对应于 BoxLayout 的 Y_AXIS 常量。

添加一个表并重用这个面板
将向 itemScrollPane 中添加一个名为 itemTable 的 JTable。还要在现有的 mainPanel 中放上另外一个 BoxLayoutPanel —— buttonPanel。这样会提供一个面板来存放按钮。这一次,不用编写任何新的 Java 代码,而是您正在使用现有的类在 app-context.xml 中定义并组合更多的 bean:
<bean id="mainPanel" class="todo.ui.BoxLayoutPanel"
        init-method="init">
    <property name="axis">
      <!-- "1" corresponds to BoxLayout.Y_AXIS -->
      <!-- Spring can access constants, but it's more complex -->
      <value>1</value>
    </property>
    <property name="panelComponents">
      <list>
        <ref bean="itemScrollPane"/>
        <ref bean="buttonPanel"/>
      </list>
    </property>
</bean>
<bean id="itemScrollPane" class="javax.swing.JScrollPane">
    <constructor-arg>
      <ref bean="itemTable"/>
    </constructor-arg>
</bean>
<bean id="itemTable" class="javax.swing.JTable">
</bean>
<bean id="buttonPanel" class=
     "todo.ui.BoxLayoutPanel" init-method="init">
    <property name="axis">
      <!-- "0" corresponds to BoxLayout.X_AXIS -->
      <value>0</value>
    </property>
    <property name="panelComponents">
      <list>
      </list>
    </property>
</bean>

定义表模型,清单如下:
package todo.ui;
import java.util.List;
import javax.swing.table.AbstractTableModel;
@SuppressWarnings("serial")
public class ItemTableModel extends AbstractTableModel{
@SuppressWarnings("unchecked")
List itemList;
    public boolean isCellEditable(final int rowIndex, final int columnIndex) {
        return true;
    }
    public int getColumnCount() {
        return 1;
    }
    public String getColumnName(final int column) {
        return "项目列表";
    }
    @SuppressWarnings("unchecked")
public void setItemList(final List itemList) {
        this.itemList = itemList;
    }
    public int getRowCount() {
        return itemList.size();
    }
    @SuppressWarnings("unchecked")
public void setValueAt(final Object value,
                           final int rowIndex, final int columnIndex) {
        itemList.set(rowIndex, value);
    }
    public Object getValueAt(final int rowIndex, final int columnIndex) {
        return itemList.get(rowIndex);
    }
}

显示列表中的项:
<bean id="itemTable" class="javax.swing.JTable">
    <property name="model">
      <ref bean="itemTableModel"/>
    </property>
</bean>
<bean id="itemTableModel" class="todo.ui.ItemTableModel">
    <property name="itemList">
      <ref bean="itemList"/>
    </property>
</bean>
<bean id="itemList" class="java.util.ArrayList">
    <constructor-arg>
      <list>
        <value>项目一</value>
        <value>项目二</value>
        <value>项目三</value>
      </list>
    </constructor-arg>
</bean>


创建 to-do 列表:完成 —— 按钮和监听程序
创建按钮和监听程序
首先创建一个 JButton 的子类 ActionListenerButton:
package todo.ui.button;
import java.awt.event.ActionListener;
import javax.swing.JButton;
@SuppressWarnings("serial")
public class ActionListenerButton extends JButton {
private ActionListener actionListener;

     public void setActionListener(ActionListener actionListener) {
         this.actionListener = actionListener;
     }
     public void init() {
         this.addActionListener(actionListener);
     }
}

然后创建一个抽象超类 ListTableActionListener,其中包含了按钮所需要的 ActionListeners 通用功能:
package todo.ui.button;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.JTable;
public abstract class ListTableActionListener implements ActionListener {
protected JTable table;
    @SuppressWarnings("unchecked")
protected List list;

    @SuppressWarnings("unchecked")
public void setList(List list) {
        this.list = list;
    }
    public void setTable(JTable itemTable) {
        this.table = itemTable;
    }
}

然后创建 AddNewButtonActionListener:
package todo.ui.button;
import java.awt.event.ActionEvent;
public class AddNewButtonActionListener extends ListTableActionListener{
@SuppressWarnings("unchecked")
@Override
public void actionPerformed(ActionEvent e) {
      list.add("New Item");
         table.revalidate();  
}
}

然后创建 DeleteButtonActionListener:
package todo.ui.button;
import java.awt.event.ActionEvent;
public class DeleteButtonActionListener extends ListTableActionListener{
@Override
public void actionPerformed(ActionEvent e) {
   int selectedRow = table.getSelectedRow();
         if (selectedRow == -1) {
             // if there is no selected row, don't do anything
             return;
         }
         if (table.isEditing()) {
             // if we are editing the table, don't do anything
             return;
         }
         list.remove(selectedRow);
         table.revalidate();  
}
}

最后创建CloseButtonActionListener:
package todo.ui.button;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
public class CloseButtonActionListener implements ActionListener {
    private JFrame frame;
    public void setFrame(JFrame frame){
    this.frame=frame;
    }
@Override
public void actionPerformed(ActionEvent e) {
   frame.setVisible(false);  
}
}

组合按钮和监听程序:
<bean id="buttonPanel" class=
     "todo.ui.BoxLayoutPanel" init-method="init">
    <property name="axis">
      <!-- "0" corresponds to BoxLayout.X_AXIS -->
      <value>0</value>
    </property>
    <property name="panelComponents">
      <list>
        <ref bean="deleteButton"/>
        <ref bean="addNewButton"/>
         <ref bean="closeButton"/>
      </list>
    </property>
</bean>
<bean id="deleteButton" class="todo.ui.button.ActionListenerButton"
        init-method="init">
    <property name="actionListener">
      <ref bean="deleteButtonActionListener"/>
    </property>
    <property name="text">
      <value>删除</value>
    </property>
</bean>
<bean id="deleteButtonActionListener"
        class="todo.ui.button.DeleteButtonActionListener">
    <property name="list">
      <ref bean="itemList"/>
    </property>
    <property name="table">
      <ref bean="itemTable"/>
    </property>
</bean>
<bean id="addNewButton" class="todo.ui.button.ActionListenerButton"
        init-method="init">
    <property name="actionListener">
      <ref bean="addNewButtonActionListener"/>
    </property>
    <property name="text">
      <value>添加</value>
    </property>
</bean>
<bean id="addNewButtonActionListener"
        class="todo.ui.button.AddNewButtonActionListener">
    <property name="list">
      <ref bean="itemList"/>
    </property>
    <property name="table">
      <ref bean="itemTable"/>
    </property>
</bean>
<bean id="closeButton" class="todo.ui.button.ActionListenerButton" init-method="init">
   <property name="actionListener">
   <ref bean="closeButtonActionListener"/>
   </property>
   <property name="text">
    <value>关闭</value>
    </property>
</bean>
<bean id="closeButtonActionListener" class="todo.ui.button.CloseButtonActionListener">
   <property name="frame">
     <ref bean="mainFrame"/>
   </property>
</bean>

此时运行,就可看到开始的效果!

读后感:spring主要为了解耦,现在web中应用非常流行,在swing中运用spring,让我的感觉就像swt和rcp的关系

原创粉丝点击