Просмотреть основные моменты работы с reflection и dynamic proxy:
- http://tutorials.jenkov.com/java-reflection/index.html
- http://restless-man.livejournal.com/24320.html
Все задачи должны быть покрыты Unit-тестами в разумных пределах.
Совместить механизмы загрузки классов и рефлексии. Дореализовать задание, разбираемое на лекции. Просканировать пакет: ru.sberbank.homework.common.entity. Найти класс, проаннотированный @Prototype вывести название класса и его версию найти у него метод и поле проаннотированные @ExperimentalFeature. Вывести их названия.
Создать сервис, реализующий интерфейс ru.sberbank.homework.common.BeanFieldCopier. Сервис должен копировать состояния одного объекта в другой, используя геттеры и сеттеры. Подробности в джвадоке к интерфейсу.
Реализовать класс, порождающий кеширующий прокси — CacheProxy с методом cache(Object service),
который принимает ссылку на сервис и возвращает кешированную версию этого сервиса*.
CacheProxy должен тоже принимать в конструкторе некоторые настройки,
например, рутовую папку в которой хранить файлы, дефолтные настройки кеша и тд.
Логика по кешированию должна навешиваться с помощью DynamicProxy.
Реализовать аннотацию @Cache для тонкой настройки кеша методов. Аннотация не только говорит о том, что результат выполнения этого метода должен кешироваться, но и о том как это делать**:
- результат хранить в памяти JVM или сериализовывать в файл
- какие аргументы метода учитывать при определении уникальности результата, а какие игнорировать(по умолчанию все аргументы учитываются). Способ остается на ваш выбор.***
- возможность указывать название файла/ключа по которому будем храниться значение. Если не задано - использовать имя метода.
- ДОПОЛНИТЕЛЬНО Если возвращаемый тип это List – возможность указывать максимальное количество элементов в нем. Т. е., если нам возвращается List с size = 1млн, мы можем сказать что в кеше достаточно хранить 100т элементов.
- ДОПОЛНИТЕЛЬНО Если мы сохраняем результат на диск, должна быть возможность указать, что данный файл надо дополнительно сжимать в zip архив.
Все возможные исключения должны быть обработаны с понятным описание, что делать, чтобы избежать ошибок. (Например, если вы пытаетесь сохранить на диск результат метода, но данный результат не сериализуем, надо кинуть исключение с понятным описанием как это исправить. Или делать это при создании прокси)
Дизайн аннотаций, атрибутов аннотаций, классов реализаций остается на ваш вкус. Код должен быть читаем, классы не перегружены логикой, классы должны лежать в нужных пакетах.
Примеры:
* Пример включения кеширования:
CacheProxy cacheProxy = new CacheProxy(...);
Service service = cacheProxy.cache(new ServiceImpl());
Loader loader = cacheProxy.cache(new LoaderImpl());
** interface Service { @Cache(cacheType = FILE, fileNamePrefix = "data", zip = true, identityBy = {String.class, double.class})
*** Например, должна быть возможность указать, что doHardWork() должен игнорировать значение второго аргумента, уникальность определяется только по String аргументу.
double r1 = service.doHardWork("work1", 10); // считает результат
double r2 = service.doHardWork("work1", 5); // результат из кеша