Closed hhfdna closed 3 years ago
HelloService is just a plain interface:
public interface HelloService {
void print(String name);
}
works fine with latest version 5.3.2, but every created instance is identical, I think it's reused by JVM not spring.
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
public class Main {
public static void main(String[] args) throws Exception {
try (AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfiguration.class)) {
System.out.println(ctx.getBean(Service.class));
//printed: Main$MyConfiguration$$Lambda$69/1658926803@1d548a08
}
}
@Configuration
@ComponentScan
static class MyConfiguration {
@Bean
@Scope("prototype")
public Service service() {
return () -> {
};
}
}
static interface Service {
void test();
}
}
Very interesting, lambda expression will be identical, but method reference will not.
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
public class Main {
public static void main(String[] args) throws Exception {
Service s1 = createService();
Service s2 = createService();
System.out.println(s1 == s2); // true created by lambda expression
try (AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfiguration.class)) {
Service service1 = ctx.getBean(Service.class);
Service service2 = ctx.getBean(Service.class);
System.out.println(service1 == service2); // false created by method reference
}
}
static Service createService() {
return s -> {
System.out.println(s);
};
}
@Configuration
@ComponentScan
static class MyConfiguration {
@Bean
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public Service service() {
return System.out::println;
}
}
static interface Service {
void print(String name);
}
}
This is due to method-references being treated differently then lambda expression by the compiler/runtime are handled.
This is due to method-references being treated differently then lambda expression by the compiler/runtime are handled.
Thanks, but it still not explain such difference.
so, the conclusion is that if i want a prototype-scoped bean, anonymouse inner class and method reference works, but lamda can't? but why?
for inner anonymouse class:
@Bean
@Scope("prototype")
public HelloService helloService(){
return new HelloService() {
@Override
public void print(String name) {
System.out.println("hello:"+name);
}
};
}
i get defferent instances for every call:
hello:prototype@com.bocsoft.demo.DIApp$1@35a3d49f
hello:prototype@com.bocsoft.demo.DIApp$1@389b0789
hello:prototype@com.bocsoft.demo.DIApp$1@13d9cbf5
hello:prototype@com.bocsoft.demo.DIApp$1@478db956
hello:prototype@com.bocsoft.demo.DIApp$1@6ca18a14
but for lamda style
@Bean
@Scope("prototype")
public HelloService helloService(){
return name -> System.out.println("hello:"+name);
}
i get the same instance for every call:
hello:prototype@com.bocsoft.demo.DIApp$$Lambda$164/41489123@34b9f960
hello:prototype@com.bocsoft.demo.DIApp$$Lambda$164/41489123@34b9f960
hello:prototype@com.bocsoft.demo.DIApp$$Lambda$164/41489123@34b9f960
hello:prototype@com.bocsoft.demo.DIApp$$Lambda$164/41489123@34b9f960
hello:prototype@com.bocsoft.demo.DIApp$$Lambda$164/41489123@34b9f960
for inner anonymouse class:
@Bean @Scope("prototype") public HelloService helloService(){ return new HelloService() { @Override public void print(String name) { System.out.println("hello:"+name); } }; }
i get defferent instances for every call:
hello:prototype@com.bocsoft.demo.DIApp$1@35a3d49f hello:prototype@com.bocsoft.demo.DIApp$1@389b0789 hello:prototype@com.bocsoft.demo.DIApp$1@13d9cbf5 hello:prototype@com.bocsoft.demo.DIApp$1@478db956 hello:prototype@com.bocsoft.demo.DIApp$1@6ca18a14
but for lamda style
@Bean @Scope("prototype") public HelloService helloService(){ return name -> System.out.println("hello:"+name); }
i get the same instance for every call:
hello:prototype@com.bocsoft.demo.DIApp$$Lambda$164/41489123@34b9f960 hello:prototype@com.bocsoft.demo.DIApp$$Lambda$164/41489123@34b9f960 hello:prototype@com.bocsoft.demo.DIApp$$Lambda$164/41489123@34b9f960 hello:prototype@com.bocsoft.demo.DIApp$$Lambda$164/41489123@34b9f960 hello:prototype@com.bocsoft.demo.DIApp$$Lambda$164/41489123@34b9f960
It's prototype from spring perspective, use method reference or inner class instead if you really care identity.
ok, thx @quaff
Please note that questions like this are often better suited for Stack Overflow.
Closing this issue since the question has been answered in the comments above.
Here is my code:
it works fine. for every call, a new HelloService instance is created. but, after i changing HelloService bean to lamda style, it's not ok:
Does lamda not surpport prototype scope?