Резюме В этой статье будет обсуждаться с вами, как объединить силу аннотаций и аспектов, чтобы предоставить декларативные услуги предприятиям совместимым с EJB 3.0, в то же время обеспечивая независимость контейнеров.
1. Введение
В нашем совместном стремлении к дальнейшему улучшению производительности производства разработки программного обеспечения мы - как члены сообщества Java - как правило, обращаемся к J2EE, чтобы обеспечить более сложные технические проблемы в разработке предприятий, такие как управление распределенными транзакциями, параллельные решения и решения для распределения объектов. Руководящая идеология, стоящая за ним - эти сложные корпоративные услуги могут быть реализованы поставщиками серверов приложений и сбалансированы коммерческими разработчиками - действительно хорошей идеей. J2EE, в частности EJB, успешно предоставила платформу, на которой строятся приложения Enterprise Java.
Часть этого успеха обусловлена способностью выполнять декларативное программирование - способ разработки программы - в которой вы можете объявить об инфраструктурных услугах вместо явно закодированных с бизнес -логикой, чтобы код распространялся повсюду. EJB доказал ценность этого подхода к программированию - позволив предприятиям, таким как транзакции и безопасность быть объявленными с помощью дескриптора публикации и обработанным контейнером.
Тем не менее, за последние годы все больше и больше разработчиков поняли, что EJB приносит себе множество новых проблем в производительности команды - каждый EJB должен сопровождаться несколькими интерфейсами, с опубликованным описанием дескриптора, доступным через JNDI и т. Д. Единое тестирование на EJB за пределами контейнера также приносит дополнительные трудности.
Обратите внимание, что для прочтения этой статьи вам нужно иметь следующие инструменты:
· Java 2 SDK 1,5
· Maven 2.0 Beta 2
Цель EJB 3.0 - упростить развитие предприятия в следующих аспектах:
· Внедрение декларативных запросов на корпоративные услуги путем введения аннотаций метаданных
· Внедрение зависимости/инъекции ресурсов посредством аннотации
· Реализация развязки корпоративных бобов и специфических интерфейсов EJB
· Упрощение непрерывного хранения с помощью легкого картирования объектно-реламентального
Это похоже на весенний бриз для разработчиков EJB - они усердно работали над разработкой, тестированием и поддержанием EJB. Теперь легко написать Enterprise Bean, используя EJB 3.0, точно так же, как создание POJO (традиционный объект Java) с конкретными аннотациями, чтобы отметить его как EJB и запроса корпоративных услуг. Вот пример из EJB в общественном проекте EJB 3.0:
@stateful
Общественный класс Carbbean реализует ShoppingCart
{
частный поплавок всего;
Коды частных векторных продуктов;
public int someshoppingmethod () {...};
...
}
В заявлении EJB 3.0 по сути говорится, что то, что нужно разработчикам, является не в тяжелом весе, «один выпуск, удовлетворяющий все», а в легком и простом в использовании решение, предоставляя разработчикам определенные ассортименты. С этой целью одним из наиболее важных методов, предоставленных EJB 3.0, является отделение корпоративных бобов и API EJB. И это решение также приносит интересные производные - EJB теперь может работать не только на различных контейнерах EJB, но и внутри любой структуры приложения - эти рамки должны быть в состоянии распознавать EJB 3.0 (JSR 220) и нормальное аннотацию для объявления корпоративных услуг (JSR 250) Полем
Эта статья не обеспечивает углубленное исследование декларативного программирования, EJBS, аспектов или аннотаций. Вместо этого просто проанализируйте взаимосвязь между этими технологиями и обсудите, как их объединить новым способом для упрощения разработки приложений.
В этой статье вы узнаете, как написать компонентный боб EJB 3.0 и создать несколько простых аспектов, чтобы сделать его декларативным управлением транзакциями, безопасности и инъекцией ресурсов. Я надеюсь, что вы сможете извлечь выгоду из этого упражнения:
· Три практических применения в обучении (инъекция зависимости, безопасность и транзакция).
· Знаком с EJB 3.0 и идеями, стоящими за ним.
Признайте, как реализовать отделение EJB от конкретных API, чтобы позволить EJB 3.0 совместимым службами реализовать только в легком весе, а не предоставляемые только EJB.
2. Пример заказа приложения полета
На протяжении всего обсуждения вы узнаете о реализации системы заказа полета, которая использует аспекты и аннотации для внедрения внедрения зависимостей, безопасности и управления транзакциями. Приложение выполняет только две функции: оно позволяет пользователям искать рейсы (рисунок 1), а затем заказывать поездку (рисунок 2). Обе операции будут надежно обработаны, чтобы позволить только идентифицированным пользователям выполнять их. Кроме того, поскольку операция «Порядок путешествия» включает в себя заказ два рейса (Out и Return Rely), операция должна быть создана в качестве транзакционного - например, оба заказа либо будут успешными, либо сбой в качестве единицы работы.
Рисунок 1. Запрос полета: Во -первых, пользователи ищут рейсы, которые соответствуют указанным критериям.
Рисунок 2. Заказ полета: Далее пользователь заказывает исходящий рейс и обратный рейс. Оба приказа либо преуспевают, либо провалились.
Это простое веб -приложение содержит несколько сервлетов, внешний вид сервиса и слой DAO (см. Рисунок 3).
Процессы, такие как конфигурация ресурсов, безопасность и управление транзакциями, будут предоставлены аспектами (реализовано с аспектом 1,5 м3) для реализации поведения в инъекциях, объявленном в аннотациях Java 5.
Рисунок 3. 3. Инъекция ресурсов
Проект объявления EJB 3.0 позволяет объявить ресурсы с помощью аннотации @Resource (это решение определено в проекте «Обычная объявление аннотации») и вводится в ваш EJB контейнером. Инъекция зависимости - это метод - использование этой техники, сущность вне объекта, а не объект, явно созданный для этого объекта, может обеспечить (внедрить) зависимость объекта. Иногда его описывают как голливудский принцип - который шутит: «Не звоните нам, мы вам позвоним».
В качестве примера возьмите класс TravelAgenceRyServiceImpl - чтобы постоянно хранить некоторые данные, этот класс должен найти реализацию интерфейса iflightDao. Традиционно это достигается с помощью завода, синглтона, локатора сервиса или какого -либо другого индивидуального решения. Среди них одно возможное решение выглядит следующим образом:
Публичный класс TravelAgenceServiceImpl реализует ittravelagenceservice
{
общественный Iflightdao Flightdao;
Public TravelagenceServiceImpl ()
{FlightDao = FlightDaOfactory.getInstance (). getFlightDao ();
Public Void Booktrip (Long OutboundFlightId, Long ReturnflightId, Int Seats)
бросает InvalidseAtsexception
{
резервирование (outboundflightid, места);
резервирование (returnflightid, места);
}
}
Вы видели, что эта реализация включает в себя создание конкретного заводского класса - он, вероятно, будет читать информацию о конфигурации, хранящуюся где -то, чтобы понять, как будет создана реализация для создания IflightDao. Если служба явно не создает свои зависимости, вводимые контейнером, детали конфигурации и создание объектов будут прокси в контейнере. Это позволяет легко соединить компоненты в приложении - с различными конфигурациями и устраняет много старомодного синглтона и заводского кода.
Реализация класса, которая опирается на реализацию Iflightdao, объявленного с помощью аннотации ресурсов JSR 250, может выглядеть так:
Публичный класс TravelAgenceServiceImpl реализует ittravelagenceservice
{
@resource (name = "flightdao")
общественный Iflightdao Flightdao;
Public Void Booktrip (Long OutboundFlightId, Long ReturnflightId, Int Seats)
бросает InvalidseAtsexception
{
резервирование (outboundflightid, места);
резервирование (returnflightid, места);
}
}
В этом случае контейнер предоставит правильную реализацию ресурса, названного «FlightDao», в класс службы. Но что, если вы хотите использовать инъекцию ресурсов сейчас, вместо того, чтобы ждать выпуска EJB 3.0? Хорошо, вы можете взять легкий контейнер - он может обеспечить инъекции зависимости, такие как контейнер Spring или Pico. Тем не менее, я не понимаю, что существует легкий контейнер - он может использовать ресурсы JSR 250 для указания требований к инъекциям (хотя я с нетерпением жду некоторых в этом отношении).
Одним из решений является использование аспектов для внедрения впрыска зависимостей. Если вы используете аннотацию @Resource для этого, ваша реализация будет соответствовать способу EJB 3.0, совместимой с реализацией EJB 3.0 - и это не очень сложно для реализации. В следующем списке показан аспект, созданный с аспектом - он вводит поля, аннотированные с аннотацией @Resource:
@aspept
Общедоступный класс IncectionAspept
{
Private DevingDendanceManager Manager = New DevingDanceManager ();
@before ("get (@resource * *. *)")
public void перед AffieldAccesses (JoinPoint This Joinpoint)
бросает нелегальный каргментирование, нелегалораксексекция
{
Подпись Fieldsignature = (Fieldsignature) thisjoinpoint.getSignature ();
resource injectannotation = signature.getfield (). getannotation (resource.class);
Зависимость объекта = Manager.Resolve Зависимость (signature.getFieldType (), injectannotation.name ());
signature.getfield (). set (thisjoinpoint.getThis (), зависимость);
}
}
Все этот простой аспект делает запрос класса реализации из файла свойств (эта логика инкапсулируется в объекте DevingDanceManager) и введите его в поля, аннотируемые с аннотацией @Resource перед получением поля. Очевидно, что эта реализация не завершена, но она действительно иллюстрирует, как вы можете обеспечить инъекцию ресурсов в JSR 250, совместимо с EJB.
4. Безопасность
В дополнение к инъекции ресурсов JSR 250 и EJB 3.0 также обеспечивают безопасное представление метаданных посредством аннотации. Пакет Javax.annotation.security определяет пять аннотаций - Runas, Rolyailled, разрешение, Denyall и Rolesreferend - все это может применяться к методам для определения требований безопасности. Например, если вы хотите заявить, что метод Bookflight, перечисленный выше, может быть выполнен только абонентами с роли «пользователя», вы можете аннотировать этот метод со следующими ограничениями безопасности:
Публичный класс TravelAgenceServiceImpl реализует ittravelagenceservice
{
@resource (name = "flightdao")
общественный Iflightdao Flightdao;
@RolesAllowed («Пользователь»)
Public Void Booktrip (Long OutboundFlightId, Long ReturnflightId, Int Seats)
бросает InvalidseAtsexception
{
резервирование (outboundflightid, места);
резервирование (returnflightid, места);
}
}
В этой аннотации указывается, что контейнер отвечает за обеспечение того, чтобы только вызывающий абонент указанной роли может выполнить этот метод. Итак, теперь я покажу еще один простой аспект - он еще больше усилит ограничения безопасности в приложении:
@aspept
Общедоступный класс SecurityAspect
{
@Around ("ecupution (@javax.annotation.security.roleslallowed * *. *(..))")
Общедоступный объект вокруг обнаруженных меток (ходатайство
бросает бросание
{
логический Callerauthorized = false;
Rolyailled roleslowed = roleslowedforjoinpoint (thisjoinpoint);
Для (строковой роли: rolesallowed.value ())
{
if (callerinrole (роль))
{callerauthorized = true;
}
if (callerauthorized)
{return thisjoinpoint.proceed ();
еще
{
бросить новое runtimeexception («вызывающий абонент не разрешен для выполнения указанной функции»);
}
}
Частный розово -розовый рот
{
Methodignature MethodGinature = (MethodGinature) ThisJoinPoint.GetSignature ();
Метод targetMethod = methodignature.getMethod ();
return targetmethod.getannotation (rolesallowed.class);
}
Частный логический CallerinRole (строковая роль)
{...}
}
Этот аспект включает в себя выполнение всех методов - подтверждая, что вызывающий абонент является одной из ролей, указанных в аннотации, аннотирует аннотацию @Rolesalloed и гарантирует, что вызывающий абонент разрешено вызвать метод. Конечно, вы также можете использовать любой алгоритм, который вы любите авторизовать пользователя и получить его/ее роль, такую как JAAS или индивидуальное решение. В этой программе для удобства я решил прокси в контейнер сервлета.
V. дела
Транзакции становятся важной частью развития предприятия - потому что они облегчают интеграцию данных в одновременной среде. С высокого уровня транзакции могут обеспечить это с помощью нескольких или полных или неполных операций.
В отличие от аннотаций для инъекции ресурсов и безопасности, аннотации для транзакций специфичны для EJB 3.0 и не определены в нормальных аннотациях JSR 250. EJB 3.0 определяет две аннотации, связанные с транзакциями: транзакционное управление и транзакция. Аннотация TransactionManager указывает, управляется ли транзакция контейнером или бобами. В EJB 3, если эта аннотация не указана, будет использоваться транзакция, управляемая контейнером. Аннотация TransactionAttribute используется для указания уровня распространения транзакций метода. Допустимые значения - включая обязательные, требуемые, необходимые новые, поддерживаемые, неподдерживаемые и никогда не поддерживаемые - используются для определения того, требуется ли существующая транзакция или инициирована новая транзакция и т. Д.
Поскольку операция Bookflight состоит из двух шагов - заказы исходящего полета и обратного полета, упаковывая его в транзакцию, вы можете обеспечить согласованность операции. Используя аннотации транзакций EJB 3.0, это будет выглядеть следующим образом:
Публичный класс TravelAgenceServiceImpl реализует ittravelagenceservice
{
@resource (name = "flightdao")
общественный Iflightdao Flightdao;
@RolesAllowed («Пользователь»)
@TransActionAttribute (transactionAttributeType.required)
Public Void Booktrip (Long OutboundFlightId, Long ReturnflightId, Int Seats)
бросает InvalidseAtsexception
{
резервирование (outboundflightid, места);
резервирование (returnflightid, места);
}
}
И вы можете применить простой аспект для автоматического определения границ транзакций:
@aspept
Общедоступный класс TransactionAspect
{
@pointcut ("execution (@javax.ejb.transactionattribute * *. *(..))")
public void TransactionAlmethods () {}
@before ("TransactionAlmethods ()")
public void beforeTrancectionalMethods ()
{hibernateutil.begintransaction ();
@AfterReturning ("TransactionAlmethods ()")
public void после повторного повторного транзакций ()
{hibernateutil.committransaction ();
@AfterThroing ("TransactionAlmethods ()")
Public void после броска TransactionalMethods ()
{hibernateutil.rollbacktransaction ();
}
Эта реализация основана на предположении, что спячка и вездесущая резьба используется для управления сеансами Hibernate и транзакционных объектов;
6. Резюме
Используя наборы аннотаций EJB 3.0 и JSR 250, эта статья показала, как перекрестные проблемы, такие как управление ресурсами, безопасность и транзакции, реализованы в качестве аспектов. Конечно, есть много других содержимого, которое мы должны учиться дальше. Первое, что нужно выучить,-это план, предоставленный модульными проблемами по перекрестному вырезанию, путем реализации этих примеров аспектов с использованием аспекта. Во -вторых, мы видели некоторые новые идеи и концепции, стоящие за заявлением EJB 3.0, который сейчас появляется. Наконец, мы также драматически видим свободу, которая должна быть предоставлена, чтобы отделить наши бизнес -объекты от API EJB. На этом этапе все, что вы хотите сделать TravelAgenceRenceRyCeImpl - это сеанс без сохранения состояния, это добавить последнюю ноту:
@stateful
Публичный класс TravelAgenceServiceImpl реализует ittravelagenceservice
{...}
Наконец, я действительно надеюсь, что этот бесплатный подход к предоставлению корпоративных услуг принесет конкуренцию и инновации в рамках/контейнерной индустрии.