Цель Данный документ написан
потому, что бины, созданные в соответствии с принятой спецификацией, не
всегда могут работать исправно. Спецификация JavaBeans документирует
только основные требования для того, чтобы создаваемый код считался
бином. Данный документ содержит дополнительные указания, которые
позволят вам разрабатывать хорошие бины, способные правильно
функционировать практически в любой среде, включая наиболее
распространённые интерактивные среды разработки (IDEs[1]) и
броузеры.
На кого ориентирован данный документ Данный
документ предназначен как для сотрудников IBM, так и для любых других
разработчиков. Вам не обязательно следовать данным указаниям, и у вас
могут быть вполне подходящие для этого причины, но эти рекомендации
помогут вам создать лучший бин.
Чего нет в данном документе Данный рекомендации
относятся исключительно к созданию JavaBeans и не являются
универсальными для всех разработок на Java.
Должен ли Ваш программный продукт быть
бином Прежде чем приступить к созданию нового программного
продукта, стоит подумать: а не разработать ли его как JavaBean? Если
данный программный модуль сможет обеспечить функции, которыми можно
визуально манипулировать и может настраиваться для получения
определённого результата, тогда этот модуль мог бы стать "достойным
кандидатом" в JavaBean.
Чтобы решить, нужно ли вам создавать JavaBean, задайте себе следующие
вопросы, а затем примите соответствующее решение:
Должен ли это быть продукт многоразового использования? Или было
бы желательно, чтобы он был таковым?
Хотите ли вы использовать его с другими Java-компонентами
многоразового использования?
Предполагаете ли вы, что он будет использоваться в какой-нибудь из
сред разработки?
Если вы ответили положительно на все эти вопросы, тогда данный
продукт следует разрабатывать как JavaBean.
Имя Вашего бина Имена бинов должны быть
уникальными и отражать назначение бинов.
Имена должны начинаться с указания электронного адреса сервера
вашей компании в обратном порядке; как например, com.ibm. или
com.lotus и т.п.
Дополнительные элементы,включённые в имя бина, должны делать
данное имя уникальным.
Имя бина должно отражать, что из себя представляет ваш бин и что
он делает.
Имя бина должно быть удобным для общих oпераций, типа
import com.ibm.GUIbeans.*
Не забывайте, что имена визуальны. Поэтому старайтесь не включать
в названия бинов названия предприятий, подразделений, акронимы,
состоящие из нескольких букв, имена авторов и другую информацию,
которая не имеет смысла для заказчика.
Используйте общепринятые названия для соответствующего действия.
Например, если вы владеете пакетом com.ibm.beans.*, предполагается,
что в этом пакете хранятся все бины IBM, поскольку это то, чего
ожидает от нас заказчик.
Спецификация JavaBeans
Вы должны обеспечить конструктор с нулевым списком аргументов,
чтобы иметь возможность создать бин с помощью Beans.instantiate().
Вы должны следовать указанным моделям проектирования для событий,
свойств и методов для поддержки интроспекции.
Любой бин должен обеспечивать процесс сохранения информации с
помощью реализации интерфейса сериализации (Serializable) или
экстернализации (Externalizable).
Вы должны понимать семантику сериализации ваших членов-данных и
объявить все несериализуемые члены-данные как transient.
Сериализация подразумевает, что все нестатические члены-данные,
необъявленные как transient, будут сериализоваться по умолчанию.
Сериализации не подлежат слушатели событий, генерируемых вашим
бином. Объявите ваш вектор (или векторы) слушателей как transient,
чтобы он (или они) не сериализовался по умолчанию.
Контейнер отвечает за сохранение и восстановление всех
внутрибиновских связей.
Однако, помните, что объекты, которые являются Serializable и
которые, кроме того, представляют некоторые типы AWT EventListeners,
сериализуются с помощью класса java.awt.Component; что противоречит
спецификации Java Beans.[2]
Не используйте одинаковые имена для set-методов разных свойств,
даже если эти свойства различаются типами данных. Убедитесь в том, что
свойства Вашего бина и их set- и get-методы имеют уникальные имена.
Если средство разработки использует класс Introspector компании
Sun, оно не сможет интроспектировать два set-метода с одним и тем же
именем.
Визуальные бины должны наследоваться из класса java.awt.Component,
либо из одного из его подклассов.
Кодирование
После десериализации явно проинициализируйте ваши члены-данные,
описанные как transient. При повторной инициализации членов-данных не
полагайтесь на свой конструктор. В отличие от инициализации
статических элементов, здесь отсутствует последовательность запуска,
которая обычно используется.
Вы не можете рассчитывать на то, чтобы метод или свойство
вызывались или устанавливались в определённом порядке. При разработке
бина нельзя предполагать, что существует какой-то порядок вызова
методов и что все доступные свойства могут устанавливаться в любой
момент и всегда отображать своё текущее значение. Однако, если вашему
бину требуется определённый порядок установки свойств или вызова
методов, вы должны при создании бина обеспечить такой механизм,
который в случае нарушения этой последовательности мог бы справиться с
данной ситуацией.
Конструкторы не должны генерировать исключительные ситуации.
Ваш бин должен сообщать о событии, когда внутри него происходят
существенные изменения.
Для генерации конкретного события используйте соответствующий
класс событий вместо одного общего класса с флагом в eventData. Это
облегчит процесс связывания в визуальных средствах разработки.
По возможности, свойства должны быть bound. Обычно оказывается
хорошим решением использовать свойства bound для объектов-моделей,
разработанных таким образом, чтобы за ними могли наблюдать объекты
пользовательского интерфейса.
Не создавайте "шумные" бины, которые посылают слишком много
сообщений о происходящих изменениях. Это вызывает снижение
производительности. Использование традиционного PropertyChangedEvent
потенциально имеет возможность создания "шумного" бина, особенно в
сочетании со свойствами bound. Так как, в принципе, свойства bound
общаются со многими объектами, то при изменении какого-то из свойств
создаётся событие, которое передаётся всем зарегистрированным
слушателям, даже тем, которым информация об изменении данного свойства
не требуется; таким образом, создаётся "шум".
Чтобы уменьшить "шум", попробуйте использовать регистрацию
сообщений и генерацию событий, основанных на <property>. В этом
случае, об изменении свойства будут уведомляться только клиенты,
работающие с этим свойством.
Основные функции бина должны иметь возможность устанавливаться и
быть доступными через свойства. Все визуальные элементы бина должны
иметь одно или более свойств, которые управляют их внешним
представлением.
При необходимости следует создать специальный редактор свойств,
который позволит упростить процесс установки данных свойств.
Каждый раз, разрабатывая бины, следует иметь ввиду возможность их
многократного использования. Если вы, как создатель бина, на стадии
разработки не видите широкого применения для своего бина, очень важно,
чтобы в нём была заложена такая возможность на будущее.
Стадия проектирования
С бином всегда должен поставляться BeanInfo-класс. Те свойства,
которыми наверняка никогда не воспользуются большинство пользователей,
отметьте как expert. Это позволит сократить размер списка свойств и
меню связей. Заполните локализованными строками displayNames и
описания для характеристик.
Вы должны иметь значок (icon) для своего бина, чтобы данный бин
можно было легко идентифицировать в любом средстве разработки, когда
это необходимо. Обеспечьте ваш бин хотя бы одним 16x16 и одним 32x32
моно и цветным значком в формате GIF. Проследите за тем, чтобы фон у
изображения значков был прозрачным, чтобы он выглядел одинаково хорошо
во всех средствах и системах.
Выберите такую насыщенность цветов значка, чтобы он выглядел
хорошо на мониторах со слабой видеокартой.
Ваш бин должен быть "жизнеспособным" уже на стадии проектирования.
Приведём пример: Если ваш бин отображает ежемесячный календарь, он
должен показывать правильный день и число, не зависимо от месяца/года,
установленных через свои свойства.
В то же время, вы можете использовать метод бина
.isDesignTime(), для того чтобы избежать сложных ресурсоёмких
вычислений, заменяя их более простыми механизмами, обеспечивающими
похожий эффект на стадии проектирования.
Все редакторы свойств должны обеспечивать Java-строку
инициализации посредством вызова метода getJavaInitializationString()
интерфейса PropertyEditor.
Это может быть альтернативой сериализации, поскольку всё, что
возвращается бином в этом методе, может использоваться интерактивной
средой разработки при генерации кода для создания сериализованной
версии бина.
На стадии разработки свойство не может быть установлено в
недопустимое значение. Установка свойства не должна ничего портить и
не должна бросать исключительную ситуацию. В худшем случае, вы можете
сделать так, чтобы редактор свойств мог визуально показывать
пользователю список допустимых значений для данного свойства и
устанавливать его на его предыдущее допустимое значение.
Кастомайзеры
Кастомайзеры должны наследоваться из java.awt.Component для того,
чтобы они могли устанавливаться внутри диалога AWT или Панели.
Кастомайзеры должны иметь нулевой конструктор.
Проследите за тем, чтобы все редакторы свойств, которыми вы
обеспечиваете ваш бин, соответствовали спецификации JavaBeans в
отношении supportsCustomEditor(), isPaintable(), getAsText(),
setAsText(), getJavaInitializationString() и всех других возможных
комбинаций этих методов.
Поддержка интернализации
Не вводите никакие строковые литералы в ваш исходный код, если
только они не являются ключами к загрузке ресурсов. Не инициализируйте
строки в блоке статической инициализации, поскольку они не могут
загружаться правильно из файла ресурсов (который должен быть открыт
первым).
Все ресурсы, которые нуждаются в переводе, должны быть отделены от
исходного кода, чтобы бин мог использоваться в региональных
установках, отличных от тех, для которых он был первоначально
предназначен.
Не используйте текст в значках.
Пакетирование и распространение
Прежде чем передать бины заказчику, всегда упаковывайте их в
JAR-файлы. Это единственный формат, на который вы можете полагаться.
Создайте точный JAR-файл manifest с правильным названием и
убедитесь, чтобы все заголовки были написаны в правильном регистре.
Файл должен иметь имя MANIFEST.MF и находиться в директории
META-INF. Убедитесь, что название файла написано правильно.
Важен регистр символов! Не все средства разработки, которые
генерируют JAR-файлы, правильно выбирают регистр символов для
построения манифест-информации в вашем Manifest-файле, поэтому вы
должны проверить и, возможно, вручную обновить манифест-информацию в
вашем JAR-файле. Название класса, который определяет JavaBean в
JAR-файле, должно быть набрано в правильном регистре и иметь вид:
Java-Bean: True Некоторые средства будут
рассматривать все другие комбинации символов (даже "true") как
"False".
Если ваш бин поставляется с другими JAR-файлами, содержащими
классы, на которые ссылается ваш бин, убедитесь, что вы правильно
документировали указания для пользователя по поиску этих классов в
среде разработки, которую он использует. Пользователь должен
проверить, что он включил эти JAR-файлы в CLASSPATH его среды
разработки, используя для этого соответствующий механизм среды
разработки.
Если какой-то класс в JAR-файле зависит от других компонентов
JAR-файла (классов или других файлов; к примеру, графических файлов)
внутри того же JAR-файла, вы должны использовать в заголовке признак
"Depends-On" для записи этого класса в файле MANIFEST. Например, если
класс MyPackage.A в вашем JAR-файле зависит от класса MyPackage.B в
том же JAR-файле, тогда вы должны сделать следующую запись для класса
A в вашем файле MANIFEST:
Name: MyPackage/A.class Depends-On: MyPackage/B.class
Точное определение всех зависимостей компонентов JAR-файла
позволяет средствам разработки, анализирующим JAR-файлы (как Bean
Extender в VisualAge WebRunner Toolkit), упаковать бин со всеми
соответствующими файлами как отдельный самостоятельный объект.
Исходный файл (или файлы) для локализуемых ресурсов бина, таких
как текст, изображения, звуковые файлы и т.п., должен упаковываться с
бином в ZIP-файл, чтобы, если возникнет необходимость, их можно было
переделать для использования бина в любых региональных установках,
отличных от тех, для которых он был первоначально предназначен.
При поставке бина мы рекомендуем паковать следующие файлы в один
файл, например, ZIP-файл:
JAR-файл, содержащий Bean-класс (или классы), и все другие
файлы, от которых он зависит, включая исходные файлы, исходные файлы
для ресурсов классов и MANIFEST-файл, соответствующий спецификации,
как указано выше.
README-файл для бина.
Соответствующий LICENSE-файл для распространения бина.
Вся необходимая информация для использования бина различными
способами; к примеру, в визуальном средстве разработки и/или
программно, в формате HTML.
Старайтесь не усложнять чрезмерно реализацию Вашего бина. Бин
должен быть многофункциональным, по возможности, как можно меньше
зависимым от внешних классов или классов из других источников.
Старайтесь упаковывать эти внешние классы, от которых зависит бин, в
его JAR-файл.
Часто средства разработки используют определённые версии
Виртуальной Машины (VM). Использование минимального количества
внешних классов, включая и те, которые разработаны компанией
JavaSoft, уменьшает возможность зависимости Вашего кода от того, что
могло измениться при очередном выпуске VM. Тогда как язык Java
стабилен, библиотеки классов, сопровождающие каждый новый выпуск,
допускают внесение значительных изменений.
Разработчики неохотно используют бин с большим числом
зависимостей от внешних классов. В этом заключается свойство
"самодостаточности" компонентного программирования.
Использование средств разработки Процесс
поддержки JavaBeans проходит быстро и порой скачкообразно. Это создаёт
трудности для производителей бинов. Ниже мы приводим рекомендации,
позволяющие JavaBeans работать практически с любыми средствами
разработки, которые существуют на данный момент:
Бин должен быть сериализуемым (Serializable), но это не значит,
что среда, в которой он выполняется, поддерживает сериализацию
(Serialization). Бин должен быть способен сериализоваться и
восстанавливаться с помощью get- и set-методов для свойств.
Некоторые средства разработки не поддерживают сохранение бинов
через сериализацию, вместо этого они используют get- и set-методы
свойств.
Сделайте все члены, к которым вложенные классы должны иметь
доступ, защищёнными (protected) или уровня пакета, но не закрытыми
(private).
Хотя доступ к закрытым членам класса пакета для вложенного
класса разрешён спецификацией Java, загрузчик класса одного из менее
распространённых средств разработки не позволяет этого и сообщает об
ошибке с помощью IllegalAccessError. Данная ошибка не возникает в
обычном Java Runtime.
Если ваш бин имеет сложный набор свойств, убедитесь, чтобы все
свойства были доступны через соответствующие редакторы свойств, даже
если в комплект входит кастомайзер.
Это позволяет вашему бину выполняться в средах разработки,
которые поддерживают только списки свойств (property sheets), а не
кастомайзер. Такие среды будут игнорировать ваш кастомайзер, но
позволят манипулировать вашими свойствами через список свойств.
Исключая одну из не очень распространённых сред разработки, вы
можете ожидать, что все остальные среды обеспечивают редакторы
свойств для встроенных типов, таких как boolean, byte, short, int,
long, float, double и классов String, Color и Font
Если вы предлагаете свой кастомайзер, убедитесь, что ваш
кастомайзер обеспечивает доступ ко всем свойствам бина, к которым
пользователь в любом случае получил бы доступ через редакторы свойств.
Это позволяет вашему бину выполняться в средах разработки, где
наличие кастомайзера заменяет доступ к свойствам через список
свойств.
Не вводите блок статической инициализации в ваш класс BeanInfo.
Перенесите этот код в конструктор класса BeanInfo.
Некоторые средства разработки блокируют выполнение статической
инициализации BeanInfo.
Когда вы используете инструмент для создания JAR-файла,
содержащего ваш бин, должна использоваться опция "0" для того, чтобы
задать режим "не архивировать; а упаковать" ("no compression; store
only").
Некоторые средства не могут правильно использовать содержимое
сжатых JAR-файлов.
Убедитесь, что в ваших JAR-файлах нет пустых директорий.
В качестве параметров методов старайтесь использовать абстрактные
классы вместо интерфейсов, что позволит пользователям связывать
объекты этих абстрактных классов с параметрами методов.
Некоторые средства, которые позволяют связывать объекты с
параметрами, не допускают данное связывание, если этот параметр
является интерфейсом.
Регистрация Вашего бина Чтобы
сделать ваш бин полезным для других разработчиков ПО, вы должны
опубликовать о нём информацию, чтобы они могли прочитать о вашем бине и,
возможно, применить его для разработки своих приложений.
Мы бы рекомендовали зарегистрировать ваш JavaBean на одном или
нескольких доступных в режиме on-line специальных серверах.
Тестирование Чтобы убедиться, что бин
работает с конкретной версией JDK, интерактивной среды разработки или
броузера, следует протестировать его в данных конкретных версиях. Не
надейтесь на возможную совместимость версий.
Сноски
1 |
Три наиболее распространённые интерактивные
среды разработки согласно проведённым опросам: Borland's JBuilder,
IBM's VisualAge for Java и Symantec's Visual Cafe. |
2 |
В частности, если ваш бин сериализуем
(Serializable) и стал одним из KeyListener, MouseListener,
MouseMotionListener, ComponentListener или FocusListener для
другого внешнего бина, с которыми ваш бин мог бы использоваться
как слушатель при десериализации исходного бина события; хотя по
спецификации JavaBeans это не предполагается. Следовательно, в
вашем readObject(), когда ваш бин десериализуется, прежде чем он
регистрируется в качестве слушателя (согласно спецификации), вы
должны сначала удалить себя как слушателя данного бина. В
противном случае, вы зарегистрируетесь дважды для одного и того же
события. Это гарантирует вас от получения двух сообщений от
каждого события, которое вы слушаете. | |