Иногда надо выполнять некоторую операцию не чаще, чем раз в столько-то времени. Например, если нам надо отображать банковскую котировку. Иногда в секунду прилетает сотня новых значений, иногда - котировка не меняется минутами.
Идея заключается в том, что при вызове операции, помещаем в очередь объект. А в другом потоке ждем, когда объект придет и, если с прошлого вызова до момента получения нового объекта прошло мало времени, спим остаток.
пятница, 11 марта 2011 г.
суббота, 19 февраля 2011 г.
Spring: lazy-init.
Рассмотрим вот этот проект.
ChildLazy объявлен как @Lazy, значит он будет загружен по первому требованию (но не раньше).
ChildNormal как @Lazy не объявлен, значит он будет загружен при старте приложения.
Composite так же не @Lazy.
Запустим SpringStart, вывод будет такой:
Видно, что LazyChild загрузился одновременно с NormalChild. Случилось это потому, что Composite, являясь бином-синглетоном, требует LazyChild в качестве своего свойства.
Задачу решает создание ScopedProxy для LazyChild: таким образом в соответствующее свойство Composite будет проставлена только обертка, а сам LazyChild создастся только в том случае, если кто-нибудь вызовет какой-нибудь метод на прокси.
Выглядеть это будет так:
Запустив, получаем:
Из последних трех строчек видно, что задача решена.
ChildLazy объявлен как @Lazy, значит он будет загружен по первому требованию (но не раньше).
ChildNormal как @Lazy не объявлен, значит он будет загружен при старте приложения.
Composite так же не @Lazy.
Запустим SpringStart, вывод будет такой:
created LazyChild created NormalChild Composite is ready Composite.printNormalChild NormalChild.print() Composite.printLazyChild LazyChild.print()
Видно, что LazyChild загрузился одновременно с NormalChild. Случилось это потому, что Composite, являясь бином-синглетоном, требует LazyChild в качестве своего свойства.
Задачу решает создание ScopedProxy для LazyChild: таким образом в соответствующее свойство Composite будет проставлена только обертка, а сам LazyChild создастся только в том случае, если кто-нибудь вызовет какой-нибудь метод на прокси.
Выглядеть это будет так:
Запустив, получаем:
created NormalChild Composite is ready Composite.printNormalChild NormalChild.print() Composite.printLazyChild created LazyChild LazyChild.print()
Из последних трех строчек видно, что задача решена.
вторник, 8 февраля 2011 г.
Компилируем rt.jar c debug информацией.
Задача: добавить debug-информацию в rt.jar.
Шаги решения:
Готовый rt.jar для jdk1.6.0_23 можно скачать тут.
Шаги решения:
- Распаковываем src.zip в c:\_temp\jdk_src\
- Запускаем консоль в папке с распакованными файлами
- Выполняем в консоли "dir /S /B *.java > build.cmd" (без кавычек)
- Открываем build.cmd любимым текстовым редактором
- Заменяем "C:\_temp\jdk_src\" на "javac -g C:\_temp\jdk_src\"
- Запускаем build.cmd
- Долго ждем
- Добавляем с заменой скомпилированные файлы в rt.jar
- Пользуемся
Готовый rt.jar для jdk1.6.0_23 можно скачать тут.
суббота, 5 февраля 2011 г.
Spring-mvc 3.0: пишем простейшее web-приложение.
В этой заметке я предлагаю попробовать "на вкус" популярный веб-фреймворк swing-mvc.
Исходный код проекта можно скачать по этой ссылке
Напишем простейший калькулятор, позволяющий складывать два числа. Выглядеть он будет так:

Spring-mvc работает так:
Будем использовать maven и структура проекта будет следующая:
pom.xml выглядит так:
Я добавил в плагины jetty, что бы можно было запускать наше приложение прямо из консоли командой:
Следующий на очереди web.xml:
В web.xml я определяю, где находится главный spring-context, определяю DispatcherServlet как сервлет по умолчанию для всего приложения. Обратите внимание, что паттерн для сервлета задан как /, а не как /* - потому как все содержимое папки WEB-INF должно обрабатываться обычным образом.
На очереди calc.jsp:
И контроллер:
Аннотацией @Controller я говорю spring'у, что методы этого класса будут обрабатывать входящие запросы (какие именно, указанно в аннотации @RequestMapping). Параметры помечены как необязательные в виду того, что при первом входе на страничку пользователь еще ничего не ввел - и эту ситуацию надо корректно обрабатывать.
И, наконец, мы добрались до ядра нашего приложения dispatcher-servlet.xml:
Сначала я настраиваю спринг использовать аннотации:
Потом говорю в каком пакете он должен искать аннотированные файлы:
Потом определяю, как из реквеста получать файлы для отображения (в данном случае в начало имени добавится "/WEB-INF/pages/", а в конце добавится ".jsp"):
Вот и все: запускаем проект, выполнив в корне mvn jetty:run и заходим броузером на страничку
http://localhost:8080/simple-swing-project/calc
И радуемся спрингу!
Исходный код проекта можно скачать по этой ссылке
Напишем простейший калькулятор, позволяющий складывать два числа. Выглядеть он будет так:
Spring-mvc работает так:
- ищется метод-контроллер, который может обработать данный запрос
- в метод передаются параметры из запроса
- метод выполняется, возвращая модель (ModelMap)
- в соответствии с ViewResolver'ом ищется jsp, которая будет отображать ответ
- найденная jsp рендерится с учетом параметров из ModelMap
Будем использовать maven и структура проекта будет следующая:
C:\WORK\SIMPLE-SPRING-PROJECT ├───src │ └───main │ ├───java │ │ └───com │ │ └───blogspot │ │ └───fuud │ │ └───java │ │ └───simple │ │ └───spring │ │ └─────SampleController.java │ └───webapp │ └───WEB-INF │ ├───pages │ │ └────calc.jsp │ ├────dispatcher-servlet.xml │ └────web.xml └───pom.xml
pom.xml выглядит так:
Я добавил в плагины jetty, что бы можно было запускать наше приложение прямо из консоли командой:
Следующий на очереди web.xml:
В web.xml я определяю, где находится главный spring-context, определяю DispatcherServlet как сервлет по умолчанию для всего приложения. Обратите внимание, что паттерн для сервлета задан как /, а не как /* - потому как все содержимое папки WEB-INF должно обрабатываться обычным образом.
На очереди calc.jsp:
И контроллер:
Аннотацией @Controller я говорю spring'у, что методы этого класса будут обрабатывать входящие запросы (какие именно, указанно в аннотации @RequestMapping). Параметры помечены как необязательные в виду того, что при первом входе на страничку пользователь еще ничего не ввел - и эту ситуацию надо корректно обрабатывать.
И, наконец, мы добрались до ядра нашего приложения dispatcher-servlet.xml:
Сначала я настраиваю спринг использовать аннотации:
Потом говорю в каком пакете он должен искать аннотированные файлы:
Потом определяю, как из реквеста получать файлы для отображения (в данном случае в начало имени добавится "/WEB-INF/pages/", а в конце добавится ".jsp"):
Вот и все: запускаем проект, выполнив в корне mvn jetty:run и заходим броузером на страничку
http://localhost:8080/simple-swing-project/calc
И радуемся спрингу!
суббота, 29 января 2011 г.
PropertyChangeSupport и AspectJ
Когда надо создать несколько java-beans с извещением об изменении свойств, обычно заводят общий класс-предок:
И тогда java-bean выглядит примерно так:
Налицо дублирование кода. Повторящийся шаблон ("XXX" - заменяет переменную часть):
Основная цель аспектов - убирать дублирующийся код, встречающийся во многих методах. Это как раз тот случай. Заодно можно будет убрать и надоедливый "extends PropertyChange".
Теперь надо подумать, как aspectJ будет отличать сеттеры, в которые надо добавить общий код от остальных. Проще всего проставить аннотацию над классом и отобрать все сеттеры с одним аргументом.
Аннотация выглядит так:
Тогда bean можно будет писать в более простом виде:
И сам аспект:
Или в annotation-style:
Теперь по шагам:
И тогда java-bean выглядит примерно так:
Налицо дублирование кода. Повторящийся шаблон ("XXX" - заменяет переменную часть):
Основная цель аспектов - убирать дублирующийся код, встречающийся во многих методах. Это как раз тот случай. Заодно можно будет убрать и надоедливый "extends PropertyChange".
Теперь надо подумать, как aspectJ будет отличать сеттеры, в которые надо добавить общий код от остальных. Проще всего проставить аннотацию над классом и отобрать все сеттеры с одним аргументом.
Аннотация выглядит так:
Тогда bean можно будет писать в более простом виде:
И сам аспект:
Или в annotation-style:
Теперь по шагам:
- Все классы, аннотированные @Bean будут наследовать PropertyChange (в случае с аннотациями они будут наследовать только интерфейс IPropertyChange, а реализация методов будет браться из PropertyChange).
Или в annotation-style:
- Все нужные нам сеттеры - это методы типа void, принимающие один параметр, находящиеся в классе, помеченные аннотацией @Bean.
Или в annotation-style:
- Перед вызовом сеттера запоминаем текущее значение свойства в переменную oldValue(//1). Выполняем сеттер (//2) и публикуем сообщение (//3).
Или в annotation-style:
вторник, 25 января 2011 г.
JavaWS и javassist
При использовании javassist из-под java-webstart возможны проблемы с поиском классов и/или с класслоадерами. В первом случае мы получим ошибку вроде javassist.NotFoundException, во втором что-нибудь вроде VerifyError.
От первого спасет ручное добавление классов в пул:
От второго: создание класса с указанием класс-лоадера:
От первого спасет ручное добавление классов в пул:
От второго: создание класса с указанием класс-лоадера:
воскресенье, 23 января 2011 г.
Debug и JavaWS
Запускаем из консоли так:
set JAVAWS_VM_ARGS="-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8200" javaws http://xxx.xx/launch.jnlpИ аттачимся дебаггером.
Подписаться на:
Сообщения (Atom)