понедельник, 28 марта 2011 г.

вторник, 22 марта 2011 г.

вторник, 15 марта 2011 г.

Простой мониторинг времён с помощью JAMon и spring-aop.

Задача классическая - подсчитать какие методы, сколько времени выполняются, и при этом не особо уродуя функциональный код. То есть зафиксировать время перед началом выполнения метода, затем время после выполнения метода, посчитать и куда-нибудь записать разницу.

Мне не хотелось выдумывать велосипед, поэтому я воспользовался простой библиотекой JAMon, где решение этой задачи выглядит тривиально :

Без spring-а (это когда не всё создаётся через IoC) :

Monitor mon = MonitorFactory.start("myMethod");
try {
    myMethod();
} finally {
    mon.stop();
}
System.out.println(MonitorFactory.getReport());


В отчёте (в виде строки с html-таблицей) будет видно количество вызовов метода, общее время, среднее , минимальное, максимальное и т.п. Для каждого значения в методе start() будут отдельные счётчики.

Теперь как это выглядит с использованием spring-aop :

В коде ничего не добавляем (только место где выводим результаты), а в конфиге пишем следующее :

 <bean id="jamonPerformanceMonitorInterceptor" class="org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor" >
   <property name="trackAllInvocations" value="true"></property>
   <property name="useDynamicLogger" value="true"></property>
</bean>

<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <property name="interceptorNames">
        <list>
           <idref bean="jamonPerformanceMonitorInterceptor"/>
        </list>
    </property>
    <property name="beanNames">
        <list>
           <value>idBean1</value>
           <value>idBean2</value>
        </list>
    </property> 

</bean>

Всё. После этого все вызовы наших зарегистрированных бинов idBean1 и idBean2 будут фиксироваться JAMon, и как и в первом случае доступ к этим данным можно получить через MonitorFactory.getReport() (или другие полезные методы этой фабрики)


P.S.: Я использую для ряда объектов прокси CGLIB. При попытке подключить aop-аннотации, я получал ошибки, а в xml-конфигурации выше, всё отрабтало отлично. Впрочем, полагаю, что я просто что-то не докрутил с аннотациями.

P.P.S.: springframework 3.0.5(http://www.springsource.org/), JAMon 2.7(http://jamonapi.sourceforge.net/)

четверг, 10 марта 2011 г.

О работе программиста и сне

Деятельность программиста сравнивается со сном. С юмором и вполне похоже.
Это вам со стороны кажется что вы просто подошли и спросили который час.
А давайте я вас подойду и спрошу в три часа ночи который час?
Чего страшного-то? Ну и что такого что вы только что заснули?
Я просто спрошу, вы ответите и спите дальше. Чего такого-то?

Весь текст : http://alexthunder.livejournal.com/290612.html

 

среда, 2 марта 2011 г.

Java. Как получить информацию о параметре универсального типа в runtime

При компиляции универсальных типов (в частности, списков(List)) в Java, как известно, информация о параметре типа (<T>) удаляется, и в рантайме получить эту информацию нельзя. Но, как говорится, если нельзя но очень хочется... :)
Сразу оговорюсь, с полями и переменными, действительно сделать ничего нельзя и определить параметр типа, который содержится внутри не получится (в смысле, что я на данный момент такого способа не знаю). А вот с параметрами метода очень даже можно !

Итак...

Задача 1

Дано :
Объект класса с методом void setMyList(List<String> param){}

Требуется :
во время выполнения, определить тип, содержащийся в списке List параметра param

Решение :

public static Class getClassName(Method method)
  Class clazz;
  Type[] types = method.getGenericParameterTypes();
  for (Type type : types) {
                // генерик
                if (type instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) type;
                    Class = (Class) pt.getActualTypeArguments()[0];
                }
                // обычный тип (не генерик)
                if (type instanceof Class) {
                    clazz = (Class) type;
                }
            }
  return clazz;
}


Как получить Method класса, я здесь останавливаться не буду, это можно почитать в статьях про reflection API.


Усложним ситуацию, и предположим, что мы инстанцировали объект, с помощью springframework, и по каким-то причинам
этот объект инстанцирован не явно, а через оболочку-прокси, с использованием CGLIB. Примером может служить создание объектов в контексте безопасности spring-security. Вобщем суть в том, что вместо объекта нашего собственного класса, мы работаем с объектом класса-прокси, и в описании метода (того самого Method) у него уже нет информации о типе генерика. Но, вода дырочку найдёт...

Задача 2

Дано :
Объект класса, инстанцированного через spring, с включённым контекстом безопасности, с методом void setMyList(List<String> param){}

Требуется :
во время выполнения, определить тип, содержащийся в списке List параметра param

Решение :
public static Class getClassNameCGILIB(Method method) {
  Class clazz;
  if (!AopUtils.isCglibProxyClass(method.getDeclaringClass())) {
     Class baseClass = method.getDeclaringClass().getSuperclass(); // исходный класс, для которого сделана заглушка
     try {
          Method baseMethod = baseClass.getMethod(method.getName(), method.getParameterTypes());
         clazz = getClassName(baseMethod);
     } catch (NoSuchMethodException e) {
         e.printStackTrace();  //TODO сделать обработку ошибок
     }   
  }
}


P.S.: Описанные методы точно работают на Sun JDK 1.6.

вторник, 1 марта 2011 г.

Разбор управленческих кейсов на happy-pm

Спасибо большое Александру Орлову и его сайту happy-pm за постоянные обновления и переработку материалов о странной :) судьбе it-менеджеров. Вот и ещё один сборный документ с разборами поведенческих кейсов http://happy-pm.com/hpm_cases.pdf