Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo

1

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

Kirill chEbba Chebunin

2

О докладе



•   Аннотации, IoC, АОП
•   АОП через IoC + аннотации
•   Далеко не новые технологии
•   В PHP мало используются

3

1. Аннотации

4

Аннотации

@Entity
public class User {/**/}

[Class]
public class User {/**/}

/** @Entity */
class User {/**/}

5

Аннотации



• Метаданные, описывающие классы,
  методы, свойства
• Компромисс между «соглашениями» и
  «конфигурацией»
• Конфигурация непосредственно в коде

6

Аннотации. Аннотации в PHP

PHPUnit – возможно, одна из первых
билиотек с использованием аннотаций.

/**
  * @expectedException RuntimeException
  */
public function testException()
{
}

7

Аннотации. Аннотации в PHP

Zend_Reflection – чтение PHPDoc тегов.

$class = new Zend_Reflection_Class(
    'MyClass'
);
$docBlock = $class->getDocblock();
$tag = $docBlock->getTag('myTag');
echo $tag->getDescription();

8

Аннотации. Аннотации в PHP

И, конечно, Doctrine 2

/** @Entity */
class MyPersistentClass
{
  /** @Column(type="integer") */
  private $id;
  /** @Column(length=50) */
  private $name; // type defaults to string
  //...
}

9

Аннотации. Аннотации в PHP

$reader = new AnnotationReader();
$reader->setDefaultAnnotationNamespace(
    'DoctrineORMMapping‘
);
$entity = $reader->getClassAnnotation(
    'MyPersistentClass',
    'DoctrineORMMappingEntity'
);
if ($entity !== null) {
    //Entity! Do smth
}

10

Аннотации. Аннотации в ZF

Можно использовать в ActionHelper’ах.

•ContextSwitch (AjaxContext)
•Cache

11

Аннотации. Аннотации в ZF

/** @ContextSwitchable */
class FooController extends
    Zend_Controller_Action
{

    /** @Context({"xml", "json"}) */
    public function barAction()
    {
        // Do smth
    }
}

12

Аннотации. Аннотации в ZF




/** @PageCache(tags={"foo", "bar"}) */
public function barAction()
{
    // Do smth
}

13

2. IoC

14

IoC. Зависимости

Что же такое зависимости?
class FooController
    extends Zend_Controller_Action
{
    public function barAction()
    {
        $service = new MyUserService();
        $service->getUser(1);
    }
}

15

IoC. Контейнер

Шаг 1. Берем готовый объект из хранилища.

•Service Locator
•Registry
•etc

16

IoC. Контейнер


// Zend_Registry
$service =
    Zend_Registry::get('userService');

// Bootstrap container
$service = $this->getInvokeArg('bootstrap')
               ->getResource('userService');

17

IoC. Интерфейсы наше все

Шаг 2. Используем интерфейсы.

interface UserService
{/**/}

class MyUserService implements UserService
{/**/}

18

IoC. Интерфейсы наше все




interface UserService
{
    public function getUser($id);
}

19

IoC. Интерфейсы наше все

class MyUserService implements UserService
{
    protected $userDao;

    public function __construct(UserDao $userDao)
    {
        $this->userDao = $userDao;
    }

    public function getUser($id)
    {
        $this->userDao->getUserById($id);
    }
}

20

IoC. Dependency Injection



• Класс прдоставляет метод/свойство для
  инъекции (внедрения) зависимости.

• Внедрением занимается вышестоящий
  компонент

21

IoC. Dependency Injection

protected $userService;

public function setUserService(
    UserService $userService)
{
    $this->userService = $userService;
}

public function barAction()
{
    $this->userService->getUser(1);
}

22

IoC. Dependency Injection




•Кто же будет заниматься внедрением?


•Как просто конфигурировать зависимости?

23

IoC. Symfony DI

• Специальные IoC контерйнеры.

• Для PHP Symfony Dependency Injection

• Есть версия для 5.+
• Есть версия для 5.3

24

IoC. Symfony DI



• Контейнер содержит описание объектов.

• ZF2 - LazyLoadingBroker

25

IoC. Symfony DI



<service id="userDao" class="NotMyUserDao">
    <!-- Some DB params for example -->
</service>

<service id="userService" class="MyUserService">
    <argument type="service" id="userDao"/>
</service>

26

IoC. Symfony DI



$container = new ContainerBuilder();
$loader = new XmlFileLoader($container);
$loader->load('path/container.xml');

/* @var $service UserService */
$service = $container->get('userService');

27

IoC. ZF + Symfony DI

Можно подменить контейнер.

$application->getBootstrap()
    ->setContainer($container);

$application->bootstrap()->run();

28

IoC. ZF + Symfony DI

А можно запустить непосредственно
ФронтКонтроллер.


$front = $container->get('frontController');
$front->dispatch();

29

IoC. ZF + Symfony DI. Проблемы

Объекты, создаваемые ZF автоматически
•Контроллеры
•ActionHelper’ы
•ViewHerlper’ы
•Плагины

30

IoC. ZF + Symfony DI. Решения

ZF 1.x

•ActionHelper для инъекции в контроллеры
•Реализация Dispatcher’а
•Наследование Zend_Controller_Action
•Наследование Zend_View

31

IoC. ZF + Symfony DI. Решения

ZF 2.x

•ActionHelper для инъекции в контроллеры
•Реализация PluginLoader’a
•Dispatcher через PluginLoader

32

3. АОП

33

АОП. Что это?

• Прадигма программирования

• Сквозная функциональность
Лог, обработка ошибок, права доступа, транзакции.


• Первая реализация - AspectJ

34

АОП. Основные понятия



• JoinPoint (Точка соединения) – метод, которому нужно добавить функциональность

• Pointcut (Срез) – набор JoinPoint’ов

35

АОП. Реализация на PHP



/** @Cached */
public function cacheMeDude() {/* */}

/** @Log */
public function plzLogMe() {/* */}

/** @Transactional */
public function iNeedTransaction() {/* */}

36

АОП. Что это?



• Aspect (Аспект)


• Advice (Совет)
   Before, After, AfterException, AfterReturn, Around

37

АОП. Что это?

Advice как метод класса.

/** @Around("@annotation(Cached)") */
public function cache(
    ProceedingJoinPoint $joinPoint)
{
    // Cache result or return from cache
}

38

АОП. Реализация на PHP

Изменить работу метода, не трогая готовый
код.

•Переопределение в рантайме (runkit, etc)
•«Предкомпилирование» кода
•Прокси классы

39

АОП. Реализация на PHP

Подмена объекта, прокси объектом.
Например, при создании в IoC контейнере.

$objectProxy =
    ProxyClass::createProxyFromObject(
        $object,
        $handler
    );

40

АОП. Реализация на PHP

Генерируем прокси-классы с помощью
Zend_CodeGenerator

class TestAOPCheProxy extends TestAOP
{
    // Override all methods
}

41

АОП. Реализация на PHP

Override всех public и protected методов
public function method($foo, $bar)
{
    return $this->invocationHandler->invoke(
        $this,
        new ReflectionMethod(
            get_parent_class(__CLASS__),
            __FUNCTION__
        ),
        func_get_args()
    );
}

42

АОП. Реализация на PHP



/** @Cached */
public function cacheMeDude() {/* */}

/** @Log */
public function plzLogMe() {/* */}

/** @Transactional */
public function iNeedTransaction() {/* */}

43

АОП. Реализация на PHP

$aopedObject->cacheMeDude();
•ProxyClass::cacheMeDude();
   – Handler::invoke()
      • CacheAspect::cache()
         – ? OriginalClass::cacheMeDude()

44

АОП. Заключение



• Не панацея

• Может усложнить систему

• Тестирование

45

The End

Спасибо за внимание.

Kirill chEbba Chebunin
Email: iam@chebba.org
Twitter: iamchEbba

More Related Content

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

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