35
Copyleft by Diego Tarábola e Denise Goya 1 Inversão de Controle - IoC Tópicos (Avançados) de Programação Orientada a Objetos Prof. Fabio Kon DCC - IME - USP Diego Tarábola e Denise Goya outubro/2006

Inversão de Controle - IoC

  • Upload
    casper

  • View
    40

  • Download
    2

Embed Size (px)

DESCRIPTION

Inversão de Controle - IoC. Tópicos (Avançados) de Programação Orientada a Objetos Prof. Fabio Kon DCC - IME - USP Diego Tarábola e Denise Goya outubro/2006. Inversão de Controle - IoC. Princípio de Hollywood: “Não nos ligue, nós ligaremos”. Dependência de componentes. - PowerPoint PPT Presentation

Citation preview

Page 1: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 1

Inversão de Controle - IoC

Tópicos (Avançados) de Programação Orientada a Objetos

Prof. Fabio KonDCC - IME - USP

Diego Tarábola e Denise Goya

outubro/2006

Page 2: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 2

Inversão de Controle - IoC

Princípio de Hollywood: “Não nos ligue, nós ligaremos”.

Dependência de componentes.

Dependência de componentes também conhecida como colaboradores de objetos.

O objeto que exige dependência é conhecido como objeto dependente.

Arcabouço é responsável pela execução da operação.

Ocorre em tempo de execução.

Visão Geral

Page 3: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 3

public class A{ private B b; public A(){

b=new B(); }

}

Classe A precisa de uma referência para a Classe B.Classe B é uma classe concreta que tem um construtor padrão.Classe A possui uma instância de B.Nenhuma outra classe pode acessar uma instância da Classe B [Mal06].

Inversão de Controle — Motivação

1 - diagrama UML de seqüência

Cenário 1

Page 4: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 4

Objeto a possui referência para os objetos c e b.

public class A{ private B b;

public A(){ C c=new C(); b=new B(c); }}

Inversão de Controle — Motivação

2 - diagrama UML de seqüência

Cenário 2

Page 5: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 5

A precisa de uma referência para B, e não precisa saber como B é instanciado.

B pode ser uma interface, uma classe abstrata ou concreta.

Antes de instanciar a classe A, precisa de uma referência para a classe B.

public class A{ private B b; public A(){ } public setB(B b){ this.b=b; } }

Inversão de Controle — Motivação

3 - diagrama UML de seqüência

Cenário 3

Page 6: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 6

Tipos de Inversão de Controle

Inversão de Controle

Procura por Dependência

Injeção de Dependência

Contextualized Dependency

Lookup

Dependency Pull

Interface Setter Construtor

Page 7: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 7

Inversão de Controle (IoC) possui dois tipos [Har05]:

Injeção de Dependência (Dependency Injection)

Procura por Dependência (Dependency Lookup)

Injeção de Dependência sempre diz respeito a IoC, mas IoC nem sempre referencia Injeção de Dependência

Tipos de Inversão de Controle

Page 8: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 8

Procura por Dependência: um componente deve obter uma referência para uma

dependência; dois subtipos:

Dependency Pull Contextualized Dependency Lookup (CDL)

Injeção de Dependência: as dependências são literalmente injetadas (incluídas) três subtipos:

Interface – Tipo 1 Setter – Tipo 2 Constructor – Tipo 3

Tipos de Inversão de Controle

Page 9: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 9

Spring

Avalon

PicoContainer

HiveMind

Excalibur: Fortress

Resin

Copland (Ruby)

Mentawai

Contêineres de Inversão de Controle

Page 10: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 10

Procura por Dependência com Spring

public static void main(String[] args) throws Exception {

// get the bean factoryBeanFactory factory = getBeanFactory();

MessageRenderer mr = (MessageRenderer) factory.getBean("renderer");mr.render();

}

Procura por Dependência — Dependency Pull

As dependências são obtidas através de um registro assim que necessário;

Mecanismo para encontrar componentes que gerenciam o arcabouço.

Page 11: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 11

Interface do Componente para CDL com Spring

public interface ManagedComponent {

public void performLookup(Container container);

}

Procura por Dependência — Contextualized Dependency Lookup (CDL)

Semelhante ao Dependency Pull;

Procura é execuada pelo contêiner que está gerenciando o recurso e não a partir de um registro central;

CDL funciona através da implementação de uma interface.

Page 12: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 12

Obtendo dependência com o CDL

public class ContextualizedDependencyLookup implements ManagedComponent {

private Dependency dep;

public void performLookup(Container container) {this.dep = (Dependency) container.getDependency("myDependency");

}}

Procura por Dependência — Contextualized Dependency Lookup (CDL)

Executa o método performLookup() implementado pelo componente;

O componente pode procurar sua dependência utilizando a interface Container.

Page 13: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 13

Injeção de Dependência pelo Construtor com Spring

public class ConstructorInjection {

private Dependency dep;

public ConstructorInjection(Dependency dep) {this.dep = dep;

}}

Injeção de Dependência — por meio de Construtor

Dependência do componente é disponibilizada através de seu(s) construtor(es);

O argumento recebido será sua dependência.

Page 14: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 14

Injeção de Dependência através do método Setter com Spring

public class SetterInjection {

private Dependency dep;

public void setMyDependency(Dependency dep) {this.dep = dep;

}}

Injeção de Dependência — por meio de método Setter

O contêiner IoC injeta um componente de dependência através de seu método set (JavaBean);

O componente setter permite um conjunto de dependências que o contêiner de inversão de controle pode gerenciar.

Page 15: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 15

Injeção de Dependência através de Interface. Exemplo no arcabouço Avalon

public interface InjectFinder {

public void injectFinder(MovieFinder finder);}

public class MovieLister implements InjectFinder {

public void injectFinder(MovieFinder finder){this.finder = finder;

}

Injeção de Dependência — por meio de Interface [Fow06]

Componente de dependência através de uma interface;

A interface InjectFinder será definida por qualquer um que fornecer a interface MovieFinder (no exemplo abaixo).

Page 16: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 16

public class Tester {

private Container container;

private void configureContainer(){container = new Container();registerComponents(); registerInjectors(); container.start();

}}

Injeção de Dependência — por meio de Interface

Exemplo: Classe de Teste no Avalon: configura os componentes e os

injetores.

Page 17: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 17

private void registerInjectors(){

container.registerInjector(InjectFinder.class, container.lookup(“MovieFinder”));

}

Injeção de Dependência — por meio de Interface

É preciso registrar os injetores que irão injetar os componentes dependentes;

Cada interface de injeção precisa de algum código para injetar o objeto dependente;

No código abaixo, registram-se os objetos injetores no contêiner:

Page 18: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 18

Injeção versus Procura

O tipo de IoC é definido pelo contêiner adotado.

Com Dependency Pull, é necessário: registrar dependências; obter referências das dependências; interagir com as dependências obtidas.

Utilizando CDL, é preciso: que as classes implementem uma interface específica; e procure por todas dependências manualmente.

Com Injeção de Dependência, as classes precisam: permitir que as dependências sejam injetadas por meio de

construtores, métodos setters ou interfaces.

Page 19: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 19

Contêiner de Inversão de Controle

Arcabouços incluem contêineres de IoC;

Arcabouços manifestam inversão de controle em tempo de execução, por meio de retorno de chamadas [SGN04] ;

Chamadas invocam métodos hook de componentes definidos pela aplicação, sempre que ocorre algum evento;

Na ocorrência de um evento, o arcabouço chama de volta um método virtual num componente de aplicação pré-registrado;

O componente executa o processamento definido pela aplicação, em resposta ao evento;

O controle é alternado entre o arcabouço e a aplicação.

Page 20: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 20

Contêiner de Inversão de Controle

Exemplo: Recebimento de chamada telefônica [POSA 2]

Uma companhia de telefone possui um mecanismo IoC;

Um usuário: um tratador de evento, que está registrado junto à companhia, para tratar as chamadas ao número desse usuário.

Quando alguém chama pelo número daquele usuário, a rede notifica o tratador que um evento de requisição de chamada está pendente (via toque do telefone);

Assim que o telefone é tirado do gancho, existe uma reação a esta requisição (o tratador assume o controle), iniciando uma conversação entre as partes conectadas.

Page 21: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 21

Ex.: Injeção de Dependência com Spring

Bean: qualquer componente gerenciado pelo contêiner; configuração do bean:

armazena informações próprias e do bean do qual depende; representada por instâncias de classes que implementam a interface

BeanDefinition;

Interface BeanFactory: responsável por gerenciar componentes no contêiner; qualquer aplicação interage com o Spring por meio dessa

interface; a aplicação deve:

criar uma instância da classe que implemente essa interface; configurar com a informação de dependência.

Page 22: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 22

Ex.: Injeção de Dependência com Spring

arquivo de configuração para BeanDefinition: classe PropertiesBeanDefinitionReader ou

XmlBeanDefinitionReader

private static BeanFactory getBeanFactory() throws Exception {

// obtém a fábrica do bean DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

// cria uma definição do leitor PropertiesBeanDefinitionReader rdr = new

PropertiesBeanDefinitionReader(factory);

// lê as opções de configuração Properties props = new Properties(); props.load(new FileInputStream("./src/conf/beans.properties")); rdr.registerBeanDefinitions(props);

return factory;

}

Page 23: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 23

Ex.: Injeção de Dependência com Spring

A informação de BeanDefinition é obtida através de um arquivo de propriedades (properties).

Uma vez criada e configurada a implementação de BeanFactory, o bean é encontrado utilizando seu nome, que está configurado no arquivo de propriedades.

public static void main(String[] args) throws Exception {

// get the bean factory BeanFactory factory = getBeanFactory();

MessageRenderer mr = (MessageRenderer) factory.getBean("renderer"); mr.render();

}

Page 24: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 24

Ex.: Injeção de Dependência com Spring

Com XmlBeanDefinitionReader, é possível gerenciar a configuração do bean utilizando XML em vez de propriedades:

XmlBeanFactory é derivada de DefaultListableBeanFactory que estende a configuração utilizando XmlBeanDefinitionReader

XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource( "ch4/src/conf/beans.xml"));

Oracle oracle = (Oracle)factory.getBean("oracle");

DefaultListableBeanFactory factory = newDefaultListableBeanFactory();

XmlBeanDefinitionReader rdr = new XmlBeanDefinitionReader(factory);

rdr.loadBeanDefinitions(newFileSystemResource("src/conf/beans.xml"));

Oracle oracle = (Oracle)factory.getBean("oracle");

Page 25: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 25

Ex.: Injeção de Dependência com Spring

Configuração do bean: O ponto chave para qualquer aplicação baseada no Spring é

configurar um arquivo para sua aplicação.

Cada bean é definido com a tag <bean>, dentro de <beans>

<bean> possui dois atributos:

<id> utilizado para obter seu nome padrão

<class> especifica o tipo do bean

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

</beans>

Page 26: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 26

Ex.: Injeção de Dependência com Spring

Exemplo de configuração com XML:

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<bean id="renderer"

class="com.apress.prospring.ch2.StandardOutMessageRenderer"/>

<bean id="provider"

class="com.apress.prospring.ch2.HelloWorldMessageProvider"/>

</beans>

Page 27: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 27

Ex.: Injeção de Dependência com Spring

Lendo configuração do XML:

public class HelloWorldXml {

public static void main(String[] args) throws Exception {

// get the bean factory BeanFactory factory = getBeanFactory(); MessageRenderer mr = (MessageRenderer)factory.getBean("renderer"); MessageProvider mp = (MessageProvider)factory.getBean("provider");

mr.setMessageProvider(mp); mr.render(); }

private static BeanFactory getBeanFactory() throws Exception {

// get the bean factory XmlBeanFactory factory = new XmlBeanFactory(new

FileSystemResource("ch4/src/conf/beans.xml"));

return factory;

}

}

Page 28: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 28

Ex.: Injeção de Dependência com Spring

Usando Setter Injection

A tag <property> especifica a injeção de dependência; Para relacionar o bean “provider” a messageProvider do

bean “renderer”

A tag <ref> relaciona uma referência do bean à propriedade; Não é mais preciso utilizar o método set para injetar as

dependências.

<bean id="renderer”

class="com.apress.prospring.ch2.StandardOutMessageRenderer">

<property name="messageProvider"><ref local="provider"/>

</property>

</bean>

Page 29: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 29

Ex.: Injeção de Dependência com Spring

Configuração de Injeção de Dependência com XML:

public class HelloWorldXmlDI {

public static void main(String[] args) throws Exception {

// get the bean factory BeanFactory factory = getBeanFactory();

MessageRenderer mr = (MessageRenderer)factory.getBean("renderer"); mr.render(); }

private static BeanFactory getBeanFactory() throws Exception {

// get the bean factory XmlBeanFactory factory = new XmlBeanFactory(

new FileSystemResource("ch4/src/conf/beans.xml"));

return factory;

}

}

Page 30: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 30

Ex.: Injeção de Dependência com Spring

Usando Constructor Injection

A tag <constructor-arg> especifica a injeção de dependência, em vez da tag <property>;

É passada uma String (e não mais um bean);

Utiliza-se a tag <value> em vez da tag <ref> para especificar o valor do argumento do construtor;

<bean id="provider"

class="com.apress.prospring.ch4.ConfigurableMessageProvider">

<constructor-arg>

<value> This is a configurable message </value>

</constructor-arg>

</bean>

Page 31: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 31

Ex.: Injeção de Dependência com Spring

Configuração de Injeção de Dependência com XML:

Para passar mais de um argumento ou para utilizar mais de um construtor deve-se usar um índice, iniciando-se em 0 na tag <constructor-arg>.

public class ConfigurableMessageProvider {

private String message; public ConfigurableMessageProvider(String message){ this.message = message; } public String getMessage(){

return message; }

}

Page 32: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 32

Inversão de Controle e Padrão Reactor

Reactor: Padrão de Arquitetura [POSA 2];

Conhecido também como Dispatcher, Notifier

Contexto: Aplicação orientada a eventos que processa as informações

de forma síncrona e serial.

Problema: aplicações devem: atender muitas requisições simultaneamente, demultiplexar e despachar as indicações de eventos às

respectivas implementações de serviço.

Page 33: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 33

Inversão de Controle e Padrão Reactor

Define uma interface que permite que aplicações: registrem ou removam tratadores de eventos; sejam executadas no laço de eventos da aplicação.

Reactor utiliza um demultiplexador síncrono de evento para aguardar pela indicação de eventos que se originam de uma ou mais fontes.

Quando ocorre um evento: o demultiplexador síncrono de evento notifica o Reactor; o Reactor aciona o tratador associado, para realização do

serviço solicitado.

O Reactor inverte o fluxo de controle, pois é responsabilidade dele (e não da aplicação) em disparar os tratadores concretos para cada tipo de evento.

Page 34: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 34

Desvantagens na Inversão de Controle

Dificuldade na integração de arcabouços: quando dois ou mais arcabouços chamam

simultaneamente o código da aplicação, cada qual pressupondo seu próprio fluxo de controle;

Dificuldade na depuração do código e compreensão do fluxo: o controle é alternado entre o código da aplicação e

o código do arcabouço.

Page 35: Inversão de Controle - IoC

Copyleft by Diego Tarábola e

Denise Goya 35

Referências

[Fow06] Fowler, Martin. Inversion of Control Containers and Dependency Injection Pattern. Disponível em: http://www.martinfowler.com/articles/injection.html, acesso em 30/08/2006.

[Har05] Harrop, Rob. Machacek, Jan. Pro Spring. Capítulo 4, páginas 49 a 92. Apress, 2005.

[Mal06] Malarvannan Mani. Design Better Software with the Inversion of Control Pattern. Disponível em: http://www.devx.com/Java/Article/27583, acesso em 20/09/2006

[POSA 2] Schmidt, Douglas. Stal, Michael. Rohnert, Hans. Buschmann, Frank. Pattern-Oriented Software Architecture: Patterns for Concurrent and Networked Objects. Volume 2. Capítulo 3, páginas 175 a 214. Ed. John Wiley & Sons, 2000.

[SGN04] Schmidt, Douglas. Gokhale, Aniruddha. Natarajan, Balachandran. Leveraging Application Frameworks. ACM Queue Magazine, Vol2, Nº 5, jul-ago/2004.