1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-thinking-in-java-zh

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
13.18 可视编程和Beans.md 49 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 11.03.2025 09:15 d56454c

13.18 Визуальное программирование и Java Beans

До настоящего момента мы видели, как ценна Java для создания повторно используемых фрагментов кода. "Максимально повторно используемые" модули кода имеют классы, так как они содержат тесно связанные характеристики объекта (поля) и действия объекта (методы), которые могут быть использованы путём прямого использования или наследования.

Наследование и полиморфизм являются сутью объектно-ориентированного программирования, но в большинстве случаев при создании приложения мы хотим иметь именно те компоненты, которые нам нужны. Мы хотим установить эти компоненты в нашем дизайне так же, как электронный инженер устанавливает интегральные схемы на печатной плате (в случае Java — это веб-страницы). Это кажется способом ускорения развития методологии программирования, основанной на сборке модулей.Первый значительный успех в области "визуального программирования" принадлежит Microsoft Visual Basic (VB, визуальный Basic), а второй этап был представлен Borland Delphi (клиент/серверное средство разработки баз данных, которое также послужило основой для концепции Java Beans). Компоненты этих средств разработки характеризуются своей визуальностью, что бесспорно, поскольку они обычно представляют собой различные виды визуальных компонентов, таких как кнопка или поле ввода текста. На самом деле, визуализация часто проявляется в виде возможности точно получать доступ к работающим компонентам программы. Таким образом, часть методологии визуального программирования состоит в том, чтобы перетаскивать компоненты из палитры и помещать их на наши формы. Инструменты создания приложений пишут код программы таким образом, чтобы компоненты были созданы в выполняющемся процессе программы.Простое перетаскивание компонентов на форму обычно недостаточно для создания полноценной программы. Обычно требуется изменение характеристик компонентов, таких как цвет компонента, текст компонента, связанная с ним база данных и т. д. Характеристики могут быть изменены через свойства во время разработки. Мы можем мастерски управлять свойствами наших компонентов в инструментах создания приложений, и когда мы создаём программу, данные конфигурации сохраняются, поэтому при запуске программы данные восстанавливаются.На данном этапе мы можем привыкнуть использовать множество свойств объектов, которые также являются набором действий. При проектировании, действия визуальных компонентов могут частично представляться событиями, то есть "любое событие может произойти с компонентом". Обычно мы решаем, какие события должны происходить, и соединяем код для выполнения этих событий. Это ключевой раздел: средства сборки приложений могут динамически обращаться к компонентам (используя метаданные), чтобы выявить события и свойства, поддерживаемые этими компонентами. Как только они узнают состояние этих свойств, средства сборки приложений могут отображать свойства компонента и позволять нам изменять их (сохраняя их состояние при сборке программы), а также отображать эти события. В общем, мы можем выполнять действия с событиями, такими как двойной щелчок по событию, и средства сборки приложений создают код и связывают его с событиями. Когда происходит событие, нам нужно писать исполняющийся код. Средства сборки приложений выполняют большую часть работы за нас. В результате программа работает так, как она должна, и зависит от средств сборки приложений для управления соединениями.Успешность визуальных средств программирования объясняется тем, что они значительно ускоряют процесс создания приложений; естественно, пользовательский интерфейс является такой же важной частью приложения.## 13.18.1 Что такое Bean?

После детального анализа компонент становится уникальным экземпляром класса, фактически становясь частью кода. Основной спор заключается в способностях средств сборки приложений находить свойства и события компонентов. Для создания компонента VB разработчики должны написать правильный, но сложный код, который затем будет использоваться протоколами для демонстрации событий и свойств. Delphi — это второе поколение визуальных средств программирования, и язык программирования активно ориентирован на создание визуальных компонентов, поэтому проще создавать такие компоненты. Однако Java представила визуальное создание компонентов в виде высшего уровня "оборудования" Java Beans, поскольку Bean представляет собой класс. Теперь нам больше не требуется писать специальный код или использовать специальные языки программирования для создания Beans. На самом деле, единственное, что нам нужно сделать, это немного изменить названия методов. Имена методов сообщают средствам сборки приложений, являются ли методы свойствами, событиями или обычными методами.

В файлах Java правила именования часто ошибочно интерпретируются как "паттерн проектирования". Это очень плохо, потому что паттерны проектирования (см. главу 16) вызывают много проблем. Правила именования не являются паттернами проектирования; они довольно просты:(1) Поскольку свойства называются xxx, мы создаём два метода: getXxx() и setXxx(). Обратите внимание, что первый символ после get или set должен быть строчной буквой, чтобы образовать имя свойства. Методы get и set принимают одинаковый тип параметров. Между именами и типами свойств set и get нет связи. (2) Для булевых логических свойств мы можем использовать вышеописанные методы get и set, но также можно использовать метод is вместо get.

(3) Обычные методы Bean не подходят под вышеприведенные правила названий, однако они являются общедоступными.

(4) Для событий мы используем методы listener (слушатель). Этот подход полностью аналогичен тем методам, которые мы видели ранее: (addFooBarListener(FooBarListener) и removeFooBarListener(FooBarListener) используются для управления событиями FooBar. В большинстве случаев встроенные события и слушатели удовлетворяют наши потребности, но мы можем создать свои собственные события и интерфейсы слушателей.

Первая часть ответила на вопрос о том, какое изменение произошло от Java 1.0 до Java 1.1: некоторые методы имели слишком короткие названия, что делало переименование бесполезным. Теперь мы видим, что большинство этих изменений были сделаны для создания специальных компонентов Bean, которые должны соответствовать правилам названий get и set. Теперь, имея эти руководства, мы можем создать простой Bean:```java //: Frog.java // Простейший Java Bean package frogbean; import java.awt.; import java.awt.event.;

class Spots {}

public class Frog { private int прыжки; private Color цвет; private Spots пятна; private boolean прыгун;

public int getPryzhki() { return прыжки; }

public void setPryzhki(int новыеПрыжки) { прыжки = новыеПрыжки; }

public Color getЦвет() { return цвет; }

public void setЦвет(Color новыйЦвет) { цвет = новыйЦвет; }

public Spots getPятна() { return пятна; }

public void setПятна(Spots новыеПятна) { пятна = новыеПятна; }

public boolean isПрыгун() { return прыгун; }

public void setПрыгун(boolean п) { прыгун = п; }

public void addActionListener(ActionListener l) { //... }

public void removeActionListener(ActionListener l) { // ... }

public void addKeyListener(KeyListener l) { // ... }

public void removeKeyListener(KeyListener l) { // ... } }

  public void croak() {
    System.out.println("Ква!");
  }
}

Первоначально мы видим, что класс Bean представляет собой объект. Обычно все наши поля считаются приватными, и доступ к ним возможен только через методы. Далее следуют правила именования: свойства — `jump`, `color`, `jumper`, `spots` (обратите внимание, что эти изменения были внесены путём замены первой буквы имени свойства). Хотя внутренние имена полей совпадают с именами первых трёх примеров свойств, в случае `jumper` можно заметить, что имя свойства не заставляет нас использовать какое-либо специальное внутреннее имя для изменения (или, другими словами, иметь какие-то внутренние изменяемые свойства). Ссылка на событие Bean является `ActionEvent` и `KeyEvent`, что было выведено из названий методов `add` и `remove`, связанных с получателем. В конце стоит отметить, что обычный метод `croak()` всегда был частью Bean просто потому, что он являлся публичным методом, а не потому, что он соответствовал какому-либо правилу названий.## 13.18.2 Извлечение BeanInfo с помощью Introspector

Когда мы перемещаем Bean из палитры в окно формы, ключевые части Bean становятся доступными. Инструменты создания приложений должны иметь возможность создавать Bean (если это дефолтный конструктор, они могут это сделать) и затем вне этого контекста извлекать все необходимые данные для создания таблицы свойств и обработчиков событий.

Частичное решение этой проблемы уже было представлено в конце главы 11: отображение Java версии 1.1 позволяет находить все методы анонимного класса. Это идеально решает проблему Bean без необходимости использования специальных ключевых слов языка, как это требуется в других визуальных языках программирования. На самом деле, одной из причин добавления отображения в Java 1.1 была поддержка Beans (хотя отображение также поддерживает объединение объектов и удалённые вызовы методов). Мы можем хотеть, чтобы разработчики инструментов создания приложений могли отображать каждый Bean и исследовать его методы для поиска его свойств и событий.Это, конечно, возможно, но разработчики Java стремились предоставить стандартный интерфейс для каждого пользователя, а не только для упрощения работы с бинами (beans). Они также предлагают стандартный подход для создания более сложных бинов. Этот интерфейс представлен классом `Introspector`, где наиболее важным статическим методом является `getBeanInfo()`. Мы используем этот метод для класса, который полностью исследует класс и возвращает объект `BeanInfo`, который можно детально изучить для обнаружения его свойств, методов и событий.Обычно мы не обращаем внимания на такие вещи — мы можем использовать большинство готовых Bean и нам не обязательно знать все технические детали, работающие внизу. Мы просто перемещаем наши Bean в окна формы, настраиваем их свойства и пишем обработчики событий. Однако это интересное и образовательное занятие — использование `Introspector` для демонстрации информации о Bean. Так что давайте приступим, вот инструмент, который вы можете запустить (мы можем найти его в подкаталоге `forgbean`).

```markdown
//: BeanDumper.java
// Метод для анализа объекта Bean
import java.beans.*;
import java.lang.reflect.*;

public class BeanDumper {
    public static void dump(Class<?> bean) {
        BeanInfo bi = null;
        try {
            bi = Introspector.getBeanInfo(bean,
                    java.lang.Object.class);
        } catch (IntrospectionException ex) {
            System.out.println("Не удалось проанализировать "
                    + bean.getName());
            System.exit(1);
        }
        PropertyDescriptor[] properties = bi.getPropertyDescriptors();
        for (int i = 0; i < properties.length; i++) {
            Class<?> p = properties[i].getPropertyType();
            System.out.println("Тип свойства:\n  " + p.getName());
            System.out.println("Имя свойства:\n  "
                    + properties[i].getName());
            Method readMethod = properties[i].getReadMethod();
            if (readMethod != null)
                System.out.println("Метод чтения:\n  "
                        + readMethod.toString());
            Method writeMethod = properties[i].getWriteMethod();
            if (writeMethod != null)
                System.out.println("Метод записи:\n  "
                        + writeMethod.toString());
            System.out.println();
        }
    }
}
``````java
println("====================");
System.out.println("Открытые методы:");
MethodDescriptor[] methods = bi.getMethodDescriptors();
for (int i = 0; i < methods.length; i++) {
    System.out.println(methods[i].getMethod().toString());
}
System.out.println("======================");
System.out.println("Поддержка событий:");
EventSetDescriptor[] events = bi.getEventSetDescriptors();
for (int i = 0; i < events.length; i++) {
    System.out.println("Тип слушателя:\n  " + 
            events[i].getListenerType().getName());
    Method[] lm = events[i].getListenerMethods();
    for (int j = 0; j < lm.length; j++) {
        System.out.println("Метод слушателя:\n  " + 
                lm[j].getName());
    }
    MethodDescriptor[] lmd = events[i].getListenerMethodDescriptors();
    for (int j = 0; j < lmd.length; j++) {
        System.out.println("Дескриптор метода:\n  " + 
                lmd[j].getMethod().toString());
    }
    Method addListener = events[i].getAddListenerMethod();
    System.out.println("Метод добавления слушателя:\n  " + 
            addListener.toString());
    Method removeListener = events[i].getRemoveListenerMethod();
    System.out.println("Метод удаления слушателя:\n  " + 
            removeListener.toString());
}
# Класс BeanDumper

Класс `BeanDumper` предназначен для вывода информации о бине Java.

## Метод `dump`

### Описание
Метод `dump` принимает объект типа `Class` и выводит информацию о его свойствах, открытых методах и событиях.

### Пример использования
```java
public class Main {
    public static void main(String[] args) {
        BeanDumper.dump(MyClass.class);
    }
}
```
### Исключения
Если возникает исключение `IntrospectionException`, программа выводит сообщение об ошибке и завершается с кодом выхода 1.

### Вывод информации
#### Свойства
Для каждого свойства выводятся следующие данные:
- Тип свойства
- Имя свойства
- Метод чтения
- Метод записи

#### Открытые методы
Список всех открытых методов объекта.

#### Поддержка событий
Для каждого события выводятся следующие данные:
- Тип слушателя
- Методы слушателя
- Дескрипторы методов
- Метод добавления слушателя
- Метод удаления слушателя
```
``````java
public class BeanDumper {

   private static void dump(Class c) {
      System.out.println(c.toString());
      System.out.println("====================");
   }
}
```   // Вывод класса вашего выбора:
   public static void main(String[] args) {
      if (args.length < 1) {
         System.err.println("Использование:\n" +
            "BeanDumper полностью.квалифицированный.класс");
         System.exit(0);
      }
      Class c = null;
      try {
         c = Class.forName(args[0]);
      } catch (ClassNotFoundException ex) {
         System.err.println(
            "Не удалось найти " + args[0]);
         System.exit(0);
      }
      dump(c);
   }
}
///:~

```Метод `BeanDumper.dump()` предназначен для выполнения различных задач. В первую очередь он пытается создать объект `BeanInfo`. Если вызов методов `BeanInfo` проходит успешно, то создаётся информация о свойствах, методах и событиях. В вызове `Introspector.getBeanInfo()` можно заметить наличие дополнительного параметра, который указывает `Introspector`, где следует прекратить анализ наследования. В данном случае анализ прекращается до того, как будут рассмотрены все методы объекта, так как нас интересуют лишь некоторые аспекты.```Свойства могут быть получены с помощью метода `getPropertyDescriptors()`, который возвращает набор описаний свойств. Для каждого описания можно использовать метод `getPropertyType()` для полной проверки типов через методы свойств. Также метод `getName()` позволяет получить псевдоним каждого свойства (извлеченное из имени метода), а методы `getReadMethod()` и `getWriteMethod()` используются для чтения и записи значений свойств соответственно. Последние два метода возвращают объекты, которые могут использоваться для реального вызова соответствующих методов на объекте (это часть представления).

Для общих методов, включая методы свойств, метод `getMethodDescriptors()` возвращает набор описаний методов. Каждое описание может быть использовано для получения соответствующего метода объекта и вывода его имени.

Что касается событий, метод `getEventSetDescriptors()` возвращает набор описаний событий. Эти описания могут быть использованы для получения информации о классах слушателей, методах этих классов и методах добавления и удаления слушателей. Программа `BeanDumper` выводит всю эту информацию.

Если мы вызываем `BeanDumper` для класса `Frog`, это будет выглядеть следующим образом:

```bash
java BeanDumper frogbean.Frog
``````markdown
Класс имя: Лягушка
Тип свойства:
  Цвет
Имя свойства:
  цвет
Метод чтения:
  public Color getColor()
Метод записи:
  public void setColor(Color)
====================
Тип свойства:
  Пятна
Имя свойства:
  пятна
Метод чтения:
  public Spots getSpots()
Метод записи:
  public void setSpots(Spots)
====================
Тип свойства:
  boolean
Имя свойства:
  прыгун
Метод чтения:
  public boolean isJumper()
Метод записи:
  public void setJumper(boolean)
====================
Тип свойства:
  int
Имя свойства:
  прыжки
Метод чтения:
  public int getJumps()
Метод записи:
  public void setJumps(int)
====================
Открытые методы:
public void setJumps(int)
public void квакнуть()
public void removeActionListener(ActionListener)
public void addActionListener(ActionListener)
public int getJumps()
public void setColor(Color)
public void setSpots(Spots)
public void setJumper(boolean)
public boolean isJumper()
public void addKeyListener(KeyListener)
public Color getColor()
public void removeKeyListener(KeyListener)
public Spots getSpots()
======================
Поддержка событий:
Тип слушателя:
  KeyListener
Метод слушателя:
  keyTyped
Метод слушателя:
  keyPressed
Метод слушателя:
  keyReleased
Описание метода:
  public void keyTyped(KeyEvent)
Описание метода:
  public void keyPressed(KeyEvent)
Описание метода:
  public void keyReleased(KeyEvent)
Метод добавления слушателя:
  public void addKeyListener(KeyListener)
Метод удаления слушателя:
  public void removeKeyListener(KeyListener)
====================
Тип слушателя:
  ActionListener
Метод слушателя:
  actionPerformed
Описание метода:
  public void actionPerformed(ActionEvent)
Метод добавления слушателя:
  public void addActionListener(ActionListener)
Метод удаления слушателя:
  public void removeActionListener(ActionListener)
```  public void removeActionListener(ActionListener)
 ====================
 ```Этот результат демонстрирует большую часть того, что `Introspector` видит при создании объекта `BeanInfo` из наших бинов. Мы можем заметить типы свойств и их названия как отдельные элементы. Обратите внимание на использование строчных букв в названиях свойств. (Если название свойства начинается с нескольких прописных букв на одной строке, программа не будет выполнена.) И помните, что методы, которые мы видим здесь (например, методы чтения и записи), действительно создаются из объектов методов, которые могут использоваться для вызова соответствующих методов объекта.```Список общих методов включает несвязанные события или свойства, такие как `croak()`. Все методы в этом списке — это те методы, которые мы можем намеренно вызвать для бинов, а также инструменты построения приложений могут выбирать, чтобы вывести все эти методы, когда мы вызываем методы, тем самым упрощая нашу работу.

Наконец, мы видим полное анализирование событий в приемниках, увеличение и уменьшение методов приемников. В целом, имея `BeanInfo`, мы можем находить любое важное для бина, и мы также можем вызывать методы бина, даже если у нас нет никакой другой информации кроме самого объекта (что является характерной чертой этого подхода).

## 13.18.3 Более сложный бин

Пример программы ниже немного более сложный, хотя это не имеет особого значения. Программа представляет собой холст, который рисует маленькую окружность вокруг курсора мыши каждый раз, когда она перемещается, и активирует приемник действий. Когда кнопка мыши нажата, можно изменять размер окружности, цвет, размер и содержание отображаемых текстовых данных. `BangBean` также имеет свои собственные методы `addActionListener()` и `removeActionListener()`, поэтому мы можем добавлять приемники действий, которые будут активированы при щелчке пользователя на `BangBean`. Таким образом, мы сможем подтвердить поддерживаемые свойства и события.```java
//: BangBean.java
// Графический бин
package bangbean;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;

public class BangBean extends Canvas implements Serializable {
    protected int xm, ym;
    protected int cSize = 20; // Размер окружности
    protected String text = "Бум!";
    protected int fontSize = 48;
    protected Color tColor = Color.red;
    protected ActionListener actionListener;

    public BangBean() {
        addMouseListener(new ML());
        addMouseMotionListener(new MML());
    }

    public int getCircleSize() { return cSize; }
    public void setCircleSize(int newSize) {
        cSize = newSize;
    }

    public String getBangText() { return text; }
    public void setBangText(String newText) {
        text = newText;
    }

    public int getFontSize() { return fontSize; }
    public void setFontSize(int newSize) {
        fontSize = newSize;
    }

    public Color getTextColor() { return tColor; }
    public void setTextColor(Color newColor) {
        tColor = newColor;
    }

    public void paint(Graphics g) {
        g.setColor(Color.black);
        g.drawOval(xm - cSize/2, ym - cSize/2, cSize, cSize);
    }

    // Это одиночный слушатель, который является
    // самым простым видом управления слушателями:
    public void addActionListener(ActionListener l)
            throws TooManyListenersException {
        if(actionListener != null)
            throw new TooManyListenersException();
        actionListener = l;
    }

    public void removeActionListener(ActionListener l) {
        actionListener = null;
    }

    class ML extends MouseAdapter {
        public void mousePressed(MouseEvent e) {
            Graphics g = getGraphics();
            g.setColor(tColor);
            g.setFont(new Font("TimesRoman", Font.BOLD, fontSize));
            int width = g.getFontMetrics().stringWidth(text);
            g.drawString(text, (getSize().width - width)/2, getSize().height/2);
            g.dispose();

            // Вызов метода слушателя:
            if(actionListener != null)
                actionListener.actionPerformed(new ActionEvent(BangBean.this, ActionEvent.ACTION_PERFORMED, null));
        }
    }

    class MML extends MouseMotionAdapter {

``````java
     public void mouseMoved(MouseEvent e) {
        xm = e.getX();
        ym = e.getY();
        repaint();
      }
    }
    public Dimension getPreferredSize() {
      return new Dimension(200, 200);
    }
    // Testing BangBean:
    public static void main(String[] args) {
      BangBean bb = new BangBean();
      try {
        bb.addActionListener(new BBL());
      } catch (Exception ex) {
        System.out.println(ex.getMessage());
      }
    }
```
``````java
class BBL implements ActionListener {
    public void actionPerformed(ActionEvent ae) {
        System.out.println("Сработал слушатель!");
    }
}
}
```

```markdown
} catch(TooManyListenersException e) {}
Frame aFrame = new Frame("BangBean Test");
aFrame.addWindowListener(
  new WindowAdapter() {
    public void windowClosing(WindowEvent e) {
      System.exit(0);
    }
  });
aFrame.add(bb, BorderLayout.CENTER);
aFrame.setSize(300, 300);
aFrame.setVisible(true);
}
// Во время тестирования отправьте информацию об действиях
// в консоль:
static class BBL implements ActionListener {
  public void actionPerformed(ActionEvent e) {
    System.out.println("Действие BangBean");
  }
}
```

///:~Самое важное то, что мы заметим, что `BangBean` использует такой интерфейс сериализации. Это означает, что средства построения приложений могут использовать сериализацию для хранения всех данных для `BangBean`, после того как разработчик завершит настройку значений свойств. Когда Bean создается в качестве части запущенного приложения, эти хранимые свойства восстанавливаются, поэтому мы можем правильно получить наше проектирование.

Мы видим, что все поля, обычно работающие вместе с Bean, являются приватными — позволяют доступ только через методы, часто используя структуру "свойство".
Когда мы рассматриваем сигнатуру `addActionListener()`, мы замечаем, что она может генерировать исключение `TooManyListenerException` (слишком много слушателей). Это исключение указывает, что это одиночный тип, то есть он может уведомить только одного получателя при возникновении события. Обычно мы используем множественные типы событий, чтобы одно событие могло уведомить нескольких получателей. Однако это приведёт к проблеме, которую мы сможем подготовиться только в следующей главе, поэтому эта тема будет рассмотрена повторно (следующий раздел называется "Пересмотр Java Beans"). Одиночные типы событий избегают этой проблемы.Когда мы нажимаем кнопку мыши, текст помещается внутрь `BangBean`, а если поле действий существует, его метод `actionPerformed()` вызывается, создавая новый объект `ActionEvent` во время обработки. Каждый раз, когда мышка перемещается, её новые координаты захватываются, и область отрисовки перерисовывается (как мы видели, стирая некоторые слова на области).

Метод `main()` добавляет возможность тестирования программы из командной строки. Когда Bean находится в среде разработки, метод `main()` не используется, но наличие его очень полезно, так как он предоставляет быстрый способ тестирования. При каждом появлении события `ActionEvent` метод `main()` создаёт окно и помещает `BangBean` в него, также добавляя простой слушатель действий для вывода сообщений в консоль. Конечно, обычно средства построения приложений создают большую часть кода Bean. Когда мы запускаем `BangBean` через `BeanDumper` или помещаем `BangBean` в активируемую среду разработки Bean, мы замечаем множество дополнительных свойств и действий, выходящих за рамки вышеупомянутого кода. Это потому, что `BangBean` наследует от панели и панель является Bean, поэтому мы видим, что его свойства и события одинаково подходят.

## 13.18.4 Упаковка BeanПеред тем как мы можем поместить Bean в визуальный конструктор активируемых Beans, его сначала следует поместить в стандартный контейнер Bean, то есть JAR-файл (Java ARchive, Java архив), содержащий класс Bean и манифест-файл, который указывает, что это Bean. Манифест-файл представляет собой простой текстовый файл с структурой метаданных.Для `BangBean`, манифест-файл выглядит следующим образом:

```plaintext
Manifest-Version: 1.0

Name: bangbean/BangBean.class
Java-Bean: True
```

Первая строка указывает версию структуры манифеста, которая была опубликована компанией SUN давно. Вторая строка (пустые строки игнорируются) указывает имя файла `BangBean.class`. Третья строка указывает, что этот файл является Bean'ом. Без третьей строки, средства сборки программы не будут считать данный класс за Bean.

Сложность заключается в том, чтобы гарантировать правильность пути в поле `Name:`. Если мы обратимся к `BangBean.java`, мы заметим, что он находится в пакете `package bangbean` (так как подкаталог, где хранятся классы, назван `bangbean`). Это название должно быть указано в манифест-файле вместе с информацией о пути. Кроме того, нам следует поместить манифест-файл в корневую директорию нашего пути упаковки, что в данном примере означает помещение файла в подкаталог `bangbean`.

После этого нам следует вызвать Jar из этой же директории, используя манифест-файл, как показано ниже:

```
jar cfm BangBean.jar BangBean.mf bangbean
```

Этот пример предполагает, что мы хотим создать файл с именем `BangBean.jar` и поместить манифест в файл с именем `BangBean.mf`.Мы можем задаться вопросом: "Как поведут себя другие классы, созданные при компиляции `BangBean.java`?" Они также будут расположены в подкаталоге `bangbean`, и мы заметим, что последний параметр командной строки `jar` — это подкаталог `bangbean`. Когда мы передаем `jar` имя подкаталога, он упаковывает весь подкаталог в jar-файл (в данном случае, включая файлы исходного кода `BangBean.java`). Для наших собственных Beans мы, возможно, не будем включать файлы исходного кода.Кроме того, если мы решим распаковать упакованный JAR-файл, мы обнаружим, что наш манифест-файл отсутствует внутри него, но `jar` создаст свой собственный манифест-файл (частично на основе наших файлов), называемый `MANIFEST.MF`, и поместит его в подкаталог `META-INF` (что означает "метаданные"). Если мы откроем этот манифест-файл, мы также заметим, что `jar` добавляет цифровые подписи для каждого файла, структура которых выглядит следующим образом:

```python
Хеш-алгоритмы: SHA MD5
SHA-хэш: pDpEAG9NaeCx8aFtqPI4udSX/O0=
MD5-хэш: O4NcS1hE3Smnzlp2hj6qeg==
```

Как правило, нам не следует беспокоиться об этом, если мы хотим внести изменения, можно отредактировать наш исходный список файлов и заново вызвать `jar`, чтобы создать новый JAR-файл для наших бинов. Также мы можем просто добавить информацию о других бинах в наш список файлов, чтобы добавить их в JAR-файл.

Важно отметить, что возможно потребуется поместить каждый бин в свой собственный подкаталог, поскольку при создании JAR-файла указывается имя каталога приложения JAR и все файлы, находящиеся в подкаталогах этого каталога, помещаются в JAR-файл. Мы видим, что `Frog` и `BangBean` находятся в своих собственных подкаталогах.Как только мы правильно поместим наши бины в JAR-файл, мы сможем переместить его в среду программирования, которая может активировать бины. Используя этот метод, мы можем переходить с одного инструмента на другой, но SUN предоставляет бесплатный и эффективный тестовый инструмент для Java Beans в своём "Kit разработки бинов" (BDK) под названием `beanbox`. (Можно скачать с `www.javasoft.com`). Перед запуском `beanbox`, поместите ваши бины в `beanbox`, скопировав JAR-файл в подкаталог `jars` BDK.## 13.18.5 Поддержка более сложных бинов

Мы видим, как легко создаётся бин. В программировании практически нет ограничений. Проектирование Java Bean предлагает простой входной пункт, который можно расширять до более сложных уровней. Эти высшие уровни вопросов выходят за рамки этой книги, но они будут здесь кратко рассмотрены. Дополнительные подробности доступны по адресу `http://java.sun.com/beans`.

Мы можем добавить более сложные программы и их атрибуты в одно место. Пример выше показывает уникальный атрибут, хотя он также может представлять массив атрибутов. Это называется индексируемым атрибутом. Мы просто предоставляем соответствующий метод (ещё раз существуют правила названия для имени метода) и `Introspector` признаёт индексируемый атрибут, поэтому наш инструмент построения приложений обрабатывает это соответственно.

Атрибуты могут быть связаны, то есть они будут уведомлены другого объекта через `PropertyChangeEvent`. Другие объекты затем могут выбрать модифицировать себя в соответствии с изменениями в бине.

Атрибуты могут быть привязаны, то есть другие объекты могут отклонить изменения в атрибуте, если они недопустимы. Другие объекты используют `PropertyChangeEvent` для уведомления и генерируют `PropertyVetoException`, чтобы заблокировать изменения и восстановить первоначальное значение. Мы также можем изменять методы, которыми наши бины описываются во время проектирования:(1) Мы можем предоставить специализированную таблицу атрибутов для наших уникальных бинов. Эта общая таблица атрибутов будет использоваться всеми бинами, но при выборе нашего бина она автоматически вызывает эту специализированную таблицу.

(2) Мы можем создать специализированный редактор для определённого атрибута, так что хотя используется обычная таблица атрибутов, когда вызывается наш указанный атрибут, редактор автоматически вызывается.

(3) Мы можем предоставить специализированный класс `BeanInfo`, который генерирует информацию, отличающуюся от информации, созданной по умолчанию с помощью `Introspector`.

(4) Также возможно изменение режима "эксперт" во всех `FeatureDescriptors`, чтобы отличать базовые характеристики от более сложных.

### 13.18.6 Больше знаний о бинах

Другой спорный вопрос заключается в том, что бины не могут быть адресованы. В любое время, когда мы создаём бин, мы надеемся, что он будет работать в многопоточной среде. Это означает, что нам следует понимать выходы потока, о которых мы поговорим в следующей главе. Мы обнаружим раздел, называемый "Обзор Java Beans", который обратит внимание на этот вопрос и его решение.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-thinking-in-java-zh.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-thinking-in-java-zh.git
oschina-mirror
wizardforcel-thinking-in-java-zh
wizardforcel-thinking-in-java-zh
master