1 / 35

Inversão de Controle - IoC

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.

adelle
Download Presentation

Inversão de Controle - IoC

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Copyleft by Diego Tarábola e Denise Goya 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

  2. Copyleft by Diego Tarábola e Denise Goya 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

  3. Copyleft by Diego Tarábola e Denise Goya Inversão de Controle — Motivação Cenário 1 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]. public class A{ private B b; public A(){ b=new B(); } } 1 - diagrama UML de seqüência

  4. Copyleft by Diego Tarábola e Denise Goya Inversão de Controle — Motivação Cenário 2 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); } } 2 - diagrama UML de seqüência

  5. Copyleft by Diego Tarábola e Denise Goya Inversão de Controle — Motivação Cenário 3 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. 3 - diagrama UML de seqüência public class A{ private B b; public A(){ } public setB(B b){ this.b=b; } }

  6. Copyleft by Diego Tarábola e Denise Goya Tipos de Inversão de Controle

  7. Copyleft by Diego Tarábola e Denise Goya Tipos de Inversão de Controle • 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

  8. Copyleft by Diego Tarábola e Denise Goya Tipos de Inversão de Controle • 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

  9. Copyleft by Diego Tarábola e Denise Goya Contêineres de Inversão de Controle Spring Avalon PicoContainer HiveMind Excalibur: Fortress Resin Copland (Ruby) Mentawai

  10. Copyleft by Diego Tarábola e Denise Goya 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. Procura por Dependência com Spring public static void main(String[] args) throws Exception { // get the bean factory BeanFactory factory = getBeanFactory(); MessageRenderer mr = (MessageRenderer) factory.getBean("renderer"); mr.render(); }

  11. Copyleft by Diego Tarábola e Denise Goya 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. Interface do Componente para CDL com Spring public interface ManagedComponent { public void performLookup(Container container); }

  12. Copyleft by Diego Tarábola e Denise Goya 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. 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"); } }

  13. Copyleft by Diego Tarábola e Denise Goya 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. Injeção de Dependência pelo Construtor com Spring public class ConstructorInjection { private Dependency dep; public ConstructorInjection(Dependency dep) { this.dep = dep; } }

  14. Copyleft by Diego Tarábola e Denise Goya 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. 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; } }

  15. Copyleft by Diego Tarábola e Denise Goya 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). 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; }

  16. Copyleft by Diego Tarábola e Denise Goya Injeção de Dependência — por meio de Interface • Exemplo: • Classe de Teste no Avalon: configura os componentes e os injetores. public class Tester { private Container container; private void configureContainer(){ container = new Container(); registerComponents(); registerInjectors(); container.start(); } }

  17. Copyleft by Diego Tarábola e Denise Goya 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: private void registerInjectors(){ container.registerInjector(InjectFinder.class, container.lookup(“MovieFinder”)); }

  18. Copyleft by Diego Tarábola e Denise Goya 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.

  19. Copyleft by Diego Tarábola e Denise Goya 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.

  20. Copyleft by Diego Tarábola e Denise Goya 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.

  21. Copyleft by Diego Tarábola e Denise Goya 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.

  22. Copyleft by Diego Tarábola e Denise Goya Ex.: Injeção de Dependência com Spring • arquivo de configuração para BeanDefinition: • classe PropertiesBeanDefinitionReader ou XmlBeanDefinitionReader privatestatic 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; }

  23. Copyleft by Diego Tarábola e Denise Goya 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. publicstaticvoid main(String[] args) throws Exception { // get the bean factory BeanFactory factory = getBeanFactory(); MessageRenderer mr = (MessageRenderer) factory.getBean("renderer"); mr.render(); }

  24. Copyleft by Diego Tarábola e Denise Goya 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 DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader rdr = new XmlBeanDefinitionReader(factory); rdr.loadBeanDefinitions(new FileSystemResource("src/conf/beans.xml")); Oracle oracle = (Oracle)factory.getBean("oracle"); XmlBeanFactory factory = new XmlBeanFactory( new FileSystemResource( "ch4/src/conf/beans.xml")); Oracle oracle = (Oracle)factory.getBean("oracle");

  25. Copyleft by Diego Tarábola e Denise Goya 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>

  26. Copyleft by Diego Tarábola e Denise Goya 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>

  27. Copyleft by Diego Tarábola e Denise Goya Ex.: Injeção de Dependência com Spring • Lendo configuração do XML: publicclass HelloWorldXml { publicstaticvoid 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(); } privatestatic BeanFactory getBeanFactory() throws Exception { // get the bean factory XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("ch4/src/conf/beans.xml")); return factory; } }

  28. Copyleft by Diego Tarábola e Denise Goya 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>

  29. Copyleft by Diego Tarábola e Denise Goya Ex.: Injeção de Dependência com Spring • Configuração de Injeção de Dependência com XML: publicclass HelloWorldXmlDI { publicstaticvoid main(String[] args) throws Exception { // get the bean factory BeanFactory factory = getBeanFactory(); MessageRenderer mr = (MessageRenderer)factory.getBean("renderer"); mr.render(); } privatestatic BeanFactory getBeanFactory() throws Exception { // get the bean factory XmlBeanFactory factory = new XmlBeanFactory( new FileSystemResource("ch4/src/conf/beans.xml")); return factory; } }

  30. Copyleft by Diego Tarábola e Denise Goya 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>

  31. Copyleft by Diego Tarábola e Denise Goya 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>. publicclassConfigurableMessageProvider { private String message; public ConfigurableMessageProvider(String message){ this.message = message; } public String getMessage(){ return message; } }

  32. Copyleft by Diego Tarábola e Denise Goya 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.

  33. Copyleft by Diego Tarábola e Denise Goya 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.

  34. Copyleft by Diego Tarábola e Denise Goya 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.

  35. Copyleft by Diego Tarábola e Denise Goya 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.

More Related