Estou com uma idéia tresloucada de desenvolver uma funcionalidade que as vezes sinto falta no Spring.
Assim que eu puder quero submeter isso à lista de discussão do framework, e se acharem que é uma boa, fazer um fork e tentar desenvolver a bagaça.
Como temos aqui no fórum uma boa galera que manja muito de Spring achei que era bom algumas opiniões antes de qualquer aventura. :lol:
Minha idéia é implementar suporte à injeção dinâmica no Spring, semelhante ao modo como funciona o Jboss Seam.
Um exemplo:
Tenho um bean X de escopo Singleton, e nesse bean tenho uma dependência Y, de escopo Prototype.
No momento em que eu requisitar o bean X ao Spring, ele irá criar o bean e injetar a dependencia Y. Ok.
No segundo momento em que eu requisitar esse bean X, a dependência Y NÃO será criada novamente, pois o Spring só injeta as dependências no momento da criação do bean, e sendo um bean
Singleton, isso só ocorrerá uma vez. O que eu queria era que, sempre que eu requisitasse esse bean X, as dependências de escopo Prototype fossem novamente instanciadas e injetadas.
O Jboss Seam chama isso de “injeção dinâmica” e particularmente vejo valor nessa abordagem.
O mesmo “problema” ocorreria em um contexto de app web, onde eu tivesse um bean de sessão e dentro dele um bean de escopo request. Essa dependencia só seria criada uma única vez.
A maneira pela qual hoje eu faço isso, e é o modo recomendado na documentação, é usar lookup methods. Não gosto muito dessa abordagem e só a utilizo em último caso. Normalmente acabo passando tudo pra Prototype mesmo, e as vezes nao é o que eu gostaria.
Voces acham que essa feature seria de fato útil?
Obrigado amigos.
ps: por favor, me corrijam se estiver falando bobagem.
Não sei se entendí direito o problema mas, de qualquer maneira, você pode criar seu próprio escopo usando o Spring (tem a maneira de fazer isso na documentação).
O que eu não entendí é a maneira de criar sua instância… você quer ou não quer que os beans sejam criados novamente?
E o que eu gostaria que fossem criados e injetados novamente são os beans de escopo Prototype, não o bean Singleton.
A instancia do bean Singleton permaneceria a mesma mas, a cada vez que eu requisitar esse bean para o Spring, as dependências dele seriam injetadas novamente. Hoje o Spring não faz isso, pois ele injeta as dependências apenas UMA vez no ciclo de vida do bean, que é o momento da sua criação.
A questão, repetindo, é que eu gostaria que essas dependências fossem novamente injetadas no meu bean principal. A solução simples seria colocar tudo como Prototype, aí o Spring criaria tudo de novo a cada requisição do bean. Mas não é o que eu queria, pois desse meu bean Singleton eu quero manter a instancia, só quero criar de novo as dependências dele.
A outra solução recomendada é usar lookup-methods, mas não curto muito essa abordagem.
Um novo escopo resolveria sim… você criaria ele, e para fazer a manutenção, você mesmo cria as dependências. Para fazer isso, basta que você crie um bean que implemente Scope e faça o gerenciamento de acordo com os métodos dele. Depois que você fizer isso, você configura o gerenciador de escopos do Spring com o seu novo escopo, e pronto!
EDIT: Pensando um pouco melhor, pode não ser exatamente “saudável” para uma aplicação fazer isso, porque, se o objeto é singleton, você pode ter alguns problemas com a execução interna desse objeto. Não seria o caso de rever a necessidade que está levando a isso?
Hm…tem razão, talvez um escopo personalizado possa ser a solução, embora o escopo em si não seja o problema, e sim esse detalhe específico do ciclo de vida, o fato do Spring injetar as dependências uma única vez.
Acho que o que você comentou é algum eventual problema de concorrencia no uso desse bean Singleton, né? Tem razão…se várias threads requisitarem essa mesma instancia, e a cada requisição do bean as dependencias forem criadas de novo, hm, pode ser um perigo…mas é exatamente isso que o lookup-method faz hoje! então jeito de fazer tem
eu citei os exemplos com Singleton e Prototype, mas vou “melhorar” o exemplo em um contexto web, onde eu poderia ter um bean de sessão, ou ApplicationScoped, e nesse bean ir injetando beans de escopos “menores” (request, prototype) conforme o uso dessa sessão.