• Nenhum resultado encontrado

Quando um bean deve ser instanciado ou destruído e quantas instâncias podem ser criadas é definido pelo seu escopo (scope). Um dos objetivos do container é tirar das mãos do desenvolvedor a responsabilidade pela instanciação dos objetos.

O escopo padrão do Spring é o singleton e, portanto, é aquele adotado em todos os beans quando não definimos nossos escopos explicitamente. Um bean declarado com este escopo é instanciado uma única vez pelo container e mantido em memória até que o container seja destruído. Antes de expor as opções oferecidas pelo Spring

3.8. Escopos Casa do Código é interessante pensarmos em algumas questões que nos ajudam a escolher a opção correta de escopo para nossos beans.

Quão cara é a construção de um bean? - Imagine um bean que represente um objeto caro de ser instanciado e configurado como por exemplo um pool de conexões ou um EntityManager JPA. Estes são os tipos de objeto que queremos ver construídos uma única vez durante a execução de nossos sistemas e não toda vez que se tornam necessários por razões de performance.

O estado interno de um objeto pode ser compartilhado por mais de um usuário do sistema? - No desenvolvimento de aplicações corporativas acesso concorrente é um dos maiores problemas a ser resolvido. Em sua raiz está o estado compartilhado que é a principal razão por trás de soluções como mecanismos de sincronização. Ima- gine que no exemplo de nosso capítulo cada instância de Processador para executar seu trabalho para um usuário precise possuir um estado único para aquele usuário. Agora imagine que a instância de um usuário seja compartilhada por outro. Uma série de consequências inesperadas poderiam ocorrer. A escolha do escopo correto para nossos beans evita este tipo de situação de uma forma bastante simples.

Quanto tempo uma instânciarealmentedeve existir? - O que nos volta à pri-

meira questão: objetos cuja instanciação seja cara normalmente duram o tempo de execução do sistema. No entanto não é interessante que alguns objetos durem muito mais que uma requisição. Por exemplo: um objeto que contenha os dados digitados em um formulário web não é feito para que dure mais do que um conjunto finito (e preferencialmente pequeno) de requisições.

Estes três questionamentos abrangem a maior parte dos problemas com os quais precisamos nos preocupar no momento em que definimos o escopo de nossos beans. Mantendo-as em mente, é hora de apresentar os escopos que o Spring nos oferece por padrão e como instruir nosso container a aplicá-los em nossos objetos.

Singleton

Trata-se do escopo padrão aplicado pelo Spring. Garante que apenas uma ins- tância do bean seja instanciada pelo container e compartilhada por todos os outros beans que a usem como dependência. É recomendada nos casos abaixo:

• A construção do objeto é cara, como por exemplo um pool de conexões, o ob- jeto SessionFactory do Hibernate ou o EntityManager do JPA. Nestes casos, é interessante manter a mesma instância do objeto compartilhada por todos os

objetos clientes do sistema, garantindo assim que sua instanciação não preju- dique a performance do sistema como um todo.

• O estado do objeto pode ser compartilhado por mais de um objeto cliente sem problema ou então é interessante que o estado seja compartilhado por mais de um objeto.

No nosso exemplo o bean fonteDados é um caso em que o escopo se aplica bem. Como é uma fonte de dados, internamente esta classe poderia ter algum mecanismo de cacheamento que favorecesse chamadas subsequentes aos métodos de pesquisa implementados. É interessante observar que o escopo no entanto não foi aplicado ao bean impressor, visto que não desejamos que seu estado interno seja compartilhado por mais de um objeto cliente da mesma.

Para declarar um bean como um singleton há duas opções: você pode não fazer nada visto ser o escopo padrão usado pelo Spring ou incluir na definição deste o atributo scope com o valor singleton tal como no exemplo abaixo:

<bean id="fonteDados" class="br.com.casadocodigo.FonteDadosArquivo"

scope="singleton">

<property name="arquivo" value="/arquivos/pessoas.csv"/> </bean>

O código abaixo ilustra bem o comportamento do escopo singleton.

FonteDadosArquivo fonteDados1 =

context.getBean("fonteDados", FonteDadosArquivo.class); FonteDadosArquivo fonteDados2 =

context.getBean(FonteDadosArquivo.class); // O teste abaixo falharia caso fonteDados1 // e fonteDados2 fossem instâncias diferentes assert fonteDados1 == fonteDados2;

Prototype

O escopo prototype garante que toda vez que o container receba uma requisição por um bean uma nova instância seja criada. É normalmente adotado em situações nas quais o bean tenha curta duração. Seu uso, de acordo com as questões que apre- sentamos acima se faz recomendado quando:

3.8. Escopos Casa do Código • O seu estado não deve ser compartilhado por mais de uma classe cliente • O objeto seja útil por um curto espaço de tempo

Definimos um bean como prototype passando o valor de mesmo nome do con- texto para o atributo scope tal como no exemplo abaixo:

<bean id="processador" class="br.com.casadocodigo.Processador"

scope="prototype">

<property name="impressor" ref="impressor"/> <property name="fonteDados" ref="fonteDados"/> </bean>

Assim como no caso do escopo singleton, podemos escrever um teste bastante simples para ilustrar seu funcionamento:

Processador processador1 =

context.getBean("processador", Processador.class); Processador processador2 =

context.getBean(Processador.class);

// O teste abaixo falharia caso estivéssemos lidando // com a mesma instância

assert processador1 != processador2

Request e Session

Para o ambiente web Spring nos oferece mais dois escopos bastante interessantes que são request e session que mantém uma instância do bean durante a existência respectivamente de uma requisição e de uma sessão de usuário. Como trataremos do desenvolvimento para este ambiente apenas posteriormente neste livro, iremos expor aqui apenas um exemplo de como declaramos beans neste escopo.

<!-- Usando o escopo de sessão -->

<bean id="processador" class="br.com.casadocodigo.Processador"

scope="session"/>

<!-- Usando o escopo de requisição -->

<bean id="processador" class="br.com.casadocodigo.Processador"

scope="request"/>

É um excelente exemplo de como o escopo evita problemas de acesso concor- rente em nosso código. Usando o escopo de sessão, cada usuário do sistema possui

sua própria instância do bean, cujo estado diz respeito apenas ao que aquele usuário está fazendo naquele momento.

Escopos customizados

Os quatro escopos acima são os mais comumente usados pelo Spring Fra- mework e conseguem atender à maior parte dos casos. Uma das característi- cas mais interessantes do Spring é sua flexibilidade. Sendo assim, caso ocorra uma situação na qual os escopos oferecidos não lhe atendam, é possível criar seu próprio escopo, bastando para tal escrever uma implementação da interface org.springframework.beans.factory.config.Scope.

A escrita de escopos customizados normalmente é feita por desenvolvedores res- ponsáveis pela implementação de novos frameworks ou bibliotecas que desejem adi- cionar suporte especial ao Spring Framework. É muito útil em contextos nos quais é necessário manter os beans somente enquanto determinado tipo de conversação esteja ocorrendo como, por exemplo, em situações nas quais seja necessário tratar transações distribuídas ou integração com sistemas remotos.

Trata-se de um uso bastante específico que foge do objetivo deste livro e, por- tanto, fica aqui apenas a menção a esta possibilidade oferecida pelo framework.

No documento Casa do Código. Prefácio (páginas 60-64)