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

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

Embed Size (px)

DESCRIPTION

Some thoughts about IoC, annotations and AOP in PHP & ZF for ZFConf Ukraine 2010. Language: Russian.

Citation preview

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

Чуть сложнее чем Singleton

Аннотации, IoC, АОП

Kirill chEbba Chebunin

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

• Аннотации, IoC, АОП

• АОП через IoC + аннотации

• Далеко не новые технологии

• В PHP мало используются

О докладе

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

1. Аннотации

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

@Entitypublic class User {/**/}

[Class]

public class User {/**/}

/** @Entity */

class User {/**/}

Аннотации

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

• Метаданные, описывающие классы, методы, свойства

• Компромисс между «соглашениями» и «конфигурацией»

• Конфигурация непосредственно в коде

Аннотации

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

•ContextSwitch (AjaxContext)

•Cache

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

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

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

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

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

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

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

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

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

2. IoC

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

Что же такое зависимости?

class FooController extends Zend_Controller_Action{ public function barAction() { $service = new MyUserService(); $service->getUser(1); }}

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

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

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

•Service Locator

•Registry

•etc

IoC. Контейнер

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

// Zend_Registry

$service =

Zend_Registry::get('userService');

// Bootstrap container

$service = $this->getInvokeArg('bootstrap')

->getResource('userService');

IoC. Контейнер

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

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

interface UserService

{/**/}

class MyUserService implements UserService {/**/}

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

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

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

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

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

class MyUserService implements UserService { protected $userDao;

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

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

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

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

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

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

IoC. Dependency Injection

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

protected $userService;

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

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

IoC. Dependency Injection

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

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

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

IoC. Dependency Injection

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

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

• Для PHP Symfony Dependency Injection

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

IoC. Symfony DI

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

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

• ZF2 - LazyLoadingBroker

IoC. Symfony DI

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

<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

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

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

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

IoC. Symfony DI

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

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

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

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

IoC. ZF + Symfony DI

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

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

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

$front->dispatch();

IoC. ZF + Symfony DI

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

Объекты, создаваемые ZF автоматически

•Контроллеры

•ActionHelper’ы

•ViewHerlper’ы

•Плагины

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

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

ZF 1.x

•ActionHelper для инъекции в контроллеры

•Реализация Dispatcher’а

•Наследование Zend_Controller_Action

•Наследование Zend_View

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

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

ZF 2.x

•ActionHelper для инъекции в контроллеры

•Реализация PluginLoader’a

•Dispatcher через PluginLoader

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

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

3. АОП

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

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

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

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

АОП. Что это?

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

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

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

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

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

/** @Cached */public function cacheMeDude() {/* */} /** @Log */public function plzLogMe() {/* */} /** @Transactional */public function iNeedTransaction() {/* */}

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

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

• Aspect (Аспект)

• Advice (Совет)

Before, After, AfterException, AfterReturn, Around

АОП. Что это?

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

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

/** @Around("@annotation(Cached)") */

public function cache(

ProceedingJoinPoint $joinPoint)

{

// Cache result or return from cache

}

АОП. Что это?

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

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

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

•«Предкомпилирование» кода

•Прокси классы

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

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

Подмена объекта, прокси объектом.

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

$objectProxy =

ProxyClass::createProxyFromObject(

$object,

$handler

);

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

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

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

Zend_CodeGenerator

class TestAOPCheProxy extends TestAOP

{

// Override all methods

}

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

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

Override всех public и protected методов

public function method($foo, $bar){ return $this->invocationHandler->invoke( $this, new ReflectionMethod( get_parent_class(__CLASS__), __FUNCTION__ ), func_get_args() );}

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

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

/** @Cached */public function cacheMeDude() {/* */} /** @Log */public function plzLogMe() {/* */} /** @Transactional */public function iNeedTransaction() {/* */}

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

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

$aopedObject->cacheMeDude();•ProxyClass::cacheMeDude();

– Handler::invoke()

• CacheAspect::cache()

–? OriginalClass::cacheMeDude()

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

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

• Не панацея

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

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

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

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

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

Kirill chEbba Chebunin

Email: [email protected]

Twitter: iamchEbba

The End