Чуть сложнее
чем Singleton
Аннотации, IoC, АОП
Kirill chEbba Chebunin
• Аннотации, IoC, АОП
• АОП через IoC + аннотации
• Далеко не новые технологии
• В PHP мало используются
О докладе
1. Аннотации
@Entity
public class User {/**/}
[Class]
public class User {/**/}
/** @Entity */
class User {/**/}
Аннотации
• Метаданные, описывающие классы,
методы, свойства
• Компромисс между «соглашениями» и
«конфигурацией»
• Конфигурация непо...
PHPUnit – возможно, одна из первых
билиотек с использованием аннотаций.
/**
* @expectedException RuntimeException
*/
publi...
Zend_Reflection – чтение PHPDoc тегов.
$class = new Zend_Reflection_Class(
'MyClass'
);
$docBlock = $class->getDocblock();...
И, конечно, Doctrine 2
/** @Entity */
class MyPersistentClass
{
/** @Column(type="integer") */
private $id;
/** @Column(le...
$reader = new AnnotationReader();
$reader->setDefaultAnnotationNamespace(
'DoctrineORMMapping‘
);
$entity = $reader->getCl...
Можно использовать в ActionHelper’ах.
•ContextSwitch (AjaxContext)
•Cache
Аннотации. Аннотации в ZF
/** @ContextSwitchable */
class FooController extends
Zend_Controller_Action
{
/** @Context({"xml", "json"}) */
public fun...
/** @PageCache(tags={"foo", "bar"}) */
public function barAction()
{
// Do smth
}
Аннотации. Аннотации в ZF
2. IoC
Что же такое зависимости?
class FooController
extends Zend_Controller_Action
{
public function barAction()
{
$service = ne...
Шаг 1. Берем готовый объект из хранилища.
•Service Locator
•Registry
•etc
IoC. Контейнер
// Zend_Registry
$service =
Zend_Registry::get('userService');
// Bootstrap container
$service = $this->getInvokeArg('boot...
Шаг 2. Используем интерфейсы.
interface UserService
{/**/}
class MyUserService implements UserService
{/**/}
IoC. Интерфей...
interface UserService
{
public function getUser($id);
}
IoC. Интерфейсы наше все
class MyUserService implements UserService
{
protected $userDao;
public function __construct(UserDao $userDao)
{
$this->us...
• Класс прдоставляет метод/свойство для
инъекции (внедрения) зависимости.
• Внедрением занимается вышестоящий
компонент
Io...
protected $userService;
public function setUserService(
UserService $userService)
{
$this->userService = $userService;
}
p...
•Кто же будет заниматься внедрением?
•Как просто конфигурировать зависимости?
IoC. Dependency Injection
• Специальные IoC контерйнеры.
• Для PHP Symfony Dependency Injection
• Есть версия для 5.+
• Есть версия для 5.3
IoC. Sym...
• Контейнер содержит описание объектов.
• ZF2 - LazyLoadingBroker
IoC. Symfony DI
<service id="userDao" class="NotMyUserDao">
<!-- Some DB params for example -->
</service>
<service id="userService" class...
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container);
$loader->load('path/container.xml');
/* @var...
Можно подменить контейнер.
$application->getBootstrap()
->setContainer($container);
$application->bootstrap()->run();
IoC....
А можно запустить непосредственно
ФронтКонтроллер.
$front = $container->get('frontController');
$front->dispatch();
IoC. Z...
Объекты, создаваемые ZF автоматически
•Контроллеры
•ActionHelper’ы
•ViewHerlper’ы
•Плагины
IoC. ZF + Symfony DI. Проблемы
ZF 1.x
•ActionHelper для инъекции в контроллеры
•Реализация Dispatcher’а
•Наследование Zend_Controller_Action
•Наследовани...
ZF 2.x
•ActionHelper для инъекции в контроллеры
•Реализация PluginLoader’a
•Dispatcher через PluginLoader
IoC. ZF + Symfon...
3. АОП
• Прадигма программирования
• Сквозная функциональность
Лог, обработка ошибок, права доступа, транзакции.
• Первая реализа...
• JoinPoint (Точка соединения) – метод, которому нужно добавить функциональность
• Pointcut (Срез) – набор JoinPoint’ов
АО...
/** @Cached */
public function cacheMeDude() {/* */}
/** @Log */
public function plzLogMe() {/* */}
/** @Transactional */
...
• Aspect (Аспект)
• Advice (Совет)
Before, After, AfterException, AfterReturn, Around
АОП. Что это?
Advice как метод класса.
/** @Around("@annotation(Cached)") */
public function cache(
ProceedingJoinPoint $joinPoint)
{
//...
Изменить работу метода, не трогая готовый
код.
•Переопределение в рантайме (runkit, etc)
•«Предкомпилирование» кода
•Прокс...
Подмена объекта, прокси объектом.
Например, при создании в IoC контейнере.
$objectProxy =
ProxyClass::createProxyFromObjec...
Генерируем прокси-классы с помощью
Zend_CodeGenerator
class TestAOPCheProxy extends TestAOP
{
// Override all methods
}
АО...
Override всех public и protected методов
public function method($foo, $bar)
{
return $this->invocationHandler->invoke(
$th...
/** @Cached */
public function cacheMeDude() {/* */}
/** @Log */
public function plzLogMe() {/* */}
/** @Transactional */
...
$aopedObject->cacheMeDude();
•ProxyClass::cacheMeDude();
– Handler::invoke()
• CacheAspect::cache()
–? OriginalClass::cach...
• Не панацея
• Может усложнить систему
• Тестирование
АОП. Заключение
Спасибо за внимание.
Kirill chEbba Chebunin
Email: iam@chebba.org
Twitter: iamchEbba
The End
Upcoming SlideShare
Loading in …5
×

Чуть сложнее чем Singleton: аннотации, IOC, АОП

1,762 views

Published on

Кирилла Чебунин / Senior PHP Developer (Альпари)

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,762
On SlideShare
0
From Embeds
0
Number of Embeds
1,028
Actions
Shares
0
Downloads
22
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Чуть сложнее чем Singleton: аннотации, IOC, АОП

  1. 1. Чуть сложнее чем Singleton Аннотации, IoC, АОП Kirill chEbba Chebunin
  2. 2. • Аннотации, IoC, АОП • АОП через IoC + аннотации • Далеко не новые технологии • В PHP мало используются О докладе
  3. 3. 1. Аннотации
  4. 4. @Entity public class User {/**/} [Class] public class User {/**/} /** @Entity */ class User {/**/} Аннотации
  5. 5. • Метаданные, описывающие классы, методы, свойства • Компромисс между «соглашениями» и «конфигурацией» • Конфигурация непосредственно в коде Аннотации
  6. 6. PHPUnit – возможно, одна из первых билиотек с использованием аннотаций. /** * @expectedException RuntimeException */ public function testException() { } Аннотации. Аннотации в PHP
  7. 7. Zend_Reflection – чтение PHPDoc тегов. $class = new Zend_Reflection_Class( 'MyClass' ); $docBlock = $class->getDocblock(); $tag = $docBlock->getTag('myTag'); echo $tag->getDescription(); Аннотации. Аннотации в PHP
  8. 8. И, конечно, Doctrine 2 /** @Entity */ class MyPersistentClass { /** @Column(type="integer") */ private $id; /** @Column(length=50) */ private $name; // type defaults to string //... } Аннотации. Аннотации в PHP
  9. 9. $reader = new AnnotationReader(); $reader->setDefaultAnnotationNamespace( 'DoctrineORMMapping‘ ); $entity = $reader->getClassAnnotation( 'MyPersistentClass', 'DoctrineORMMappingEntity' ); if ($entity !== null) { //Entity! Do smth } Аннотации. Аннотации в PHP
  10. 10. Можно использовать в ActionHelper’ах. •ContextSwitch (AjaxContext) •Cache Аннотации. Аннотации в ZF
  11. 11. /** @ContextSwitchable */ class FooController extends Zend_Controller_Action { /** @Context({"xml", "json"}) */ public function barAction() { // Do smth } } Аннотации. Аннотации в ZF
  12. 12. /** @PageCache(tags={"foo", "bar"}) */ public function barAction() { // Do smth } Аннотации. Аннотации в ZF
  13. 13. 2. IoC
  14. 14. Что же такое зависимости? class FooController extends Zend_Controller_Action { public function barAction() { $service = new MyUserService(); $service->getUser(1); } } IoC. Зависимости
  15. 15. Шаг 1. Берем готовый объект из хранилища. •Service Locator •Registry •etc IoC. Контейнер
  16. 16. // Zend_Registry $service = Zend_Registry::get('userService'); // Bootstrap container $service = $this->getInvokeArg('bootstrap') ->getResource('userService'); IoC. Контейнер
  17. 17. Шаг 2. Используем интерфейсы. interface UserService {/**/} class MyUserService implements UserService {/**/} IoC. Интерфейсы наше все
  18. 18. interface UserService { public function getUser($id); } IoC. Интерфейсы наше все
  19. 19. class MyUserService implements UserService { protected $userDao; public function __construct(UserDao $userDao) { $this->userDao = $userDao; } public function getUser($id) { $this->userDao->getUserById($id); } } IoC. Интерфейсы наше все
  20. 20. • Класс прдоставляет метод/свойство для инъекции (внедрения) зависимости. • Внедрением занимается вышестоящий компонент IoC. Dependency Injection
  21. 21. protected $userService; public function setUserService( UserService $userService) { $this->userService = $userService; } public function barAction() { $this->userService->getUser(1); } IoC. Dependency Injection
  22. 22. •Кто же будет заниматься внедрением? •Как просто конфигурировать зависимости? IoC. Dependency Injection
  23. 23. • Специальные IoC контерйнеры. • Для PHP Symfony Dependency Injection • Есть версия для 5.+ • Есть версия для 5.3 IoC. Symfony DI
  24. 24. • Контейнер содержит описание объектов. • ZF2 - LazyLoadingBroker IoC. Symfony DI
  25. 25. <service id="userDao" class="NotMyUserDao"> <!-- Some DB params for example --> </service> <service id="userService" class="MyUserService"> <argument type="service" id="userDao"/> </service> IoC. Symfony DI
  26. 26. $container = new ContainerBuilder(); $loader = new XmlFileLoader($container); $loader->load('path/container.xml'); /* @var $service UserService */ $service = $container->get('userService'); IoC. Symfony DI
  27. 27. Можно подменить контейнер. $application->getBootstrap() ->setContainer($container); $application->bootstrap()->run(); IoC. ZF + Symfony DI
  28. 28. А можно запустить непосредственно ФронтКонтроллер. $front = $container->get('frontController'); $front->dispatch(); IoC. ZF + Symfony DI
  29. 29. Объекты, создаваемые ZF автоматически •Контроллеры •ActionHelper’ы •ViewHerlper’ы •Плагины IoC. ZF + Symfony DI. Проблемы
  30. 30. ZF 1.x •ActionHelper для инъекции в контроллеры •Реализация Dispatcher’а •Наследование Zend_Controller_Action •Наследование Zend_View IoC. ZF + Symfony DI. Решения
  31. 31. ZF 2.x •ActionHelper для инъекции в контроллеры •Реализация PluginLoader’a •Dispatcher через PluginLoader IoC. ZF + Symfony DI. Решения
  32. 32. 3. АОП
  33. 33. • Прадигма программирования • Сквозная функциональность Лог, обработка ошибок, права доступа, транзакции. • Первая реализация - AspectJ АОП. Что это?
  34. 34. • JoinPoint (Точка соединения) – метод, которому нужно добавить функциональность • Pointcut (Срез) – набор JoinPoint’ов АОП. Основные понятия
  35. 35. /** @Cached */ public function cacheMeDude() {/* */} /** @Log */ public function plzLogMe() {/* */} /** @Transactional */ public function iNeedTransaction() {/* */} АОП. Реализация на PHP
  36. 36. • Aspect (Аспект) • Advice (Совет) Before, After, AfterException, AfterReturn, Around АОП. Что это?
  37. 37. Advice как метод класса. /** @Around("@annotation(Cached)") */ public function cache( ProceedingJoinPoint $joinPoint) { // Cache result or return from cache } АОП. Что это?
  38. 38. Изменить работу метода, не трогая готовый код. •Переопределение в рантайме (runkit, etc) •«Предкомпилирование» кода •Прокси классы АОП. Реализация на PHP
  39. 39. Подмена объекта, прокси объектом. Например, при создании в IoC контейнере. $objectProxy = ProxyClass::createProxyFromObject( $object, $handler ); АОП. Реализация на PHP
  40. 40. Генерируем прокси-классы с помощью Zend_CodeGenerator class TestAOPCheProxy extends TestAOP { // Override all methods } АОП. Реализация на PHP
  41. 41. Override всех public и protected методов public function method($foo, $bar) { return $this->invocationHandler->invoke( $this, new ReflectionMethod( get_parent_class(__CLASS__), __FUNCTION__ ), func_get_args() ); } АОП. Реализация на PHP
  42. 42. /** @Cached */ public function cacheMeDude() {/* */} /** @Log */ public function plzLogMe() {/* */} /** @Transactional */ public function iNeedTransaction() {/* */} АОП. Реализация на PHP
  43. 43. $aopedObject->cacheMeDude(); •ProxyClass::cacheMeDude(); – Handler::invoke() • CacheAspect::cache() –? OriginalClass::cacheMeDude() АОП. Реализация на PHP
  44. 44. • Не панацея • Может усложнить систему • Тестирование АОП. Заключение
  45. 45. Спасибо за внимание. Kirill chEbba Chebunin Email: iam@chebba.org Twitter: iamchEbba The End

×