Lazy class instance creation and initialization via proxy in Spring

java, lazy-initialization, proxy, spring

Solution

I was able to replicate your behavior - the fix that I have is to simply define an interface for your NewClass, this way Java Dynamic proxies are created instead of CGLIB enhanced proxies. Then it works as expected - instantiating NewClass at the point of the methods being called.

public interface NewInterface {
    public void setI(Integer i);
    public Integer add() ;
}

public class NewClass implements NewInterface{

    private Integer i;

    public NewClass() {
        System.out.println("NewClass()");
    }

    public void setI(Integer i) {
        System.out.println("setI(): " + i);
        this.i = i;
    }

    public Integer add() {
        return i + 1;
    }
}

Problem

Is there a ready out-of-the-box solution in Spring to proxy a class so that it is CREATED (new instance) and INITIALIZED (setters called) when a method of that class is invoked? I found and tried using org.springframework.aop.target.LazyInitTargetSource. Maybe I'm doing something wrong but in the following scenario my class instance is created TWICE. Once when the bean is retrived from the context and then ONCE AGAIN when a method is called: My proxied class: ``` public class NewClass { private Integer i; public NewClass() { System.out.println("NewClass()"); } public void setI(Integer i) { System.out.println("setI(): " + i); this.i = i; } public Integer add() { return i + 1; } } ``` Spring config: ``` <bean id="newClassTarget" class="com.mycompany.spring.NewClass" lazy-init="true"> <property name="i" value="1"/> </bean> <bean id="newClass" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="targetSource"> <bean class="org.springframework.aop.target.LazyInitTargetSource"> <property name="targetBeanName"> <idref local="newClassTarget"/> </property> </bean> </property> </bean> ``` Running code: ``` public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("lazy.xml"); System.out.println("Context initialized"); System.out.println("before getting bean"); NewClass newClass = (NewClass) applicationContext.getBean("newClass"); System.out.println("after getting bean"); System.out.println("calling add()..."); System.out.println(newClass.add()); } ``` produces: ``` Context initialized before getting bean NewClass() after getting bean calling add()... NewClass() setI(): 1 2 ``` So NewClass constructor is called when getting the bean from Spring context and when calling add() method. I don't think it's nice, did I screw something up? Anyway, the first call comes from enhancer.create() in Cglib2AopProxy.getProxy(). Is seems the proxy creates an instance of the proxied class when the bean is requested, not when the first method call occures. That is not what I want. I could create my own java.lang.reflect.Proxy as a holder for my NewClass and create an instance of NewClass in handler's invoke() the first time a method is called. I would have play around with calling setters first, though. Is there any ready solution in Spring I could use to achieve: ``` Context initialized before getting bean after getting bean calling add()... NewClass() setI(): 1 2 ``` ?

Original source