campos de feijão singleton de primavera não são preenchidos

Eu preciso de um serviço (singleton se encheckbox) com alguns campos internos, como uma lista de threads pendentes (sim tudo é escrito para ser thread seguro) o problema é que se eu @autowire este bean, os campos parecem estar vazios. Ao depurar, vejo que o proxy se liga corretamente à instância (os campos CGLIB$CALLBACK_X estão corretamente vinculados ao bean preenchido) com campos preenchidos, mas os campos que ele oferece estão vazios.

As seguintes linhas de códigos dão uma ideia geral do que eu estou falando.

 @Service public class myService{ @Autowired private Monitor monitor; public List getSomething(){ return monitor.getList(); } } @Service public class myStatefulService{ //This field will be populated for sure by someone before getSomething() is called private List list; public synchronized List getSomething(){ return this.list; } //Called by other services that self inject this bean public synchronized void addToList(Object o){ this.list.add(o); } } 

Depurando a variável monitor durante a chamada getList eu recebo

 monitor => instance of correct class fields: CGLIB$BOUND => true CGLIB$CALLBACK_0.advised => proxyFactory (correct) CGLIB$CALLBACK_1.target (reference to the correct instance of myStatefulService class) fields: list => [.........] (correctly populated) CGLIB$CALLBACK_2 ..... ...... ...... ...... list => [] (the list that would be populated is empty instead) 

Você está curioso ou tem algum problema real? No entanto, aqui está uma explicação.

Ao usar CGLIB para classs de proxy, o Spring criará uma subclass chamada algo como myService$EnhancerByCGLIB . Essa class aprimorada replaceá alguns, se não todos os seus methods de negócios, para aplicar preocupações transversais em torno de seu código real.

Aqui vem a verdadeira surpresa. Esta subclass extra não chama super methods da class base. Em vez disso, ele cria uma segunda instância do myService e delega a ele. Isso significa que você tem dois objects agora: seu object real e o object aprimorado CGLIB apontando para (empacotando-o).

A class aprimorada é apenas um proxy fictício. Ele ainda tem os mesmos campos da sua class base (herdados dele), mas eles não são usados. Quando você chamar addToList() no object myService$EnhancerByCGLIB , aplicará primeiro uma lógica AOP, chamará addToList() de myService (que envolve) e aplicará a lógica AOP restante no retorno. O campo myService$EnhancerByCGLIB.list nunca é tocado.

Por que o Spring não pode usar a mesma class e delegar via super ? Eu acho que por simplicidade: primeiro crie um bean ” bruto ” e então aplique o proxy AOP durante o pós-processamento.

“Este campo será preenchido com certeza por alguém antes de getSomething () ser chamado”

Por alguém? Não, a fábrica de feijão primavera. Se você não configurá-lo, nada será preenchido.

Nem todo grão precisa estar sob o controle da Spring. Parece que você quer ter uma List que os clientes possam adicionar e remover itens de maneira segura. Se isso for verdade, remova a anotação @Autowired , crie uma nova List e exponha methods para adicionar e remover.

Eu recomendaria uma lista das novas collections simultâneas.

O CGLIB fará proxy de getters protegidos.

Então você pode ter:

 @Autowired private Monitor monitor; protected Monitor getMonitor() { return monitor; } public List getSomething(){ return getMonitor().getList(); } 

getMonitor () será intermediado por proxy para chamar getMonitor () na outra instância que tiver monitor injetado.