spring-projects / spring-framework

Spring Framework
https://spring.io/projects/spring-framework
Apache License 2.0
56.38k stars 38.05k forks source link

Lazy bean creation with callback on injection failure #33237

Closed DanielLiu1123 closed 2 months ago

DanielLiu1123 commented 2 months ago

I'm currently working on the grpc-starter project. I want to use @Autowired for injecting grpc clients (stubs). I got some ideas from Spring Cloud OpenFeign. By specifying base-packages, I can create bean definitions for all grpc clients in this package. I did it, and it works well. See grpc-start#quick-start.

I found there are still some places to improve: scanning the classpath and creating bean definitions is a time-consuming process. Not all grpc clients in this package will be used. So, there will be many unused grpc client bean definitions in the container, which is a waste.

I hope not to scan the classpath and lazily create bean definitions based on the injection point’s needs. Therefore, I want Spring to provide a callback when injection fails (e.g., NoSuchBeanDefinitionException). This callback can get injection point information to create the bean. The whole process is like “create if absent.”

snicoll commented 2 months ago

scanning the classpath and creating bean definitions is a time-consuming process

Is it? Have you timed that? If you define the application package, it should be very fast. The only waste I can see is that you may scan the same area twice.

So, there will be many unused grpc client bean definitions in the container, which is a waste.

I am not sure I got that. Perhaps a small sample that shows what you mean would be of interest.

I want Spring to provide a callback when injection fails

Sorry but I don't think we want to head in that direction. NoSuchBeanDefinitionException is "fatal" by design (i.e. it should prevent the context from starting). Also creating beans at that point in time may break many assumptions (conditions, etc).

If you look at something like Spring Data, it does create a repository implementation for you automatically the way you've described. I'd like to understand how your use case is different.

DanielLiu1123 commented 2 months ago

Is it? Have you timed that? If you define the application package, it should be very fast. The only waste I can see is that you > may scan the same area twice.

You are right, it is fast.

I am not sure I got that.

In the Java implementation of gRPC, there are three types of clients: Stub, BlockingStub, and FutureStub. In most cases, we only need to use BlockingStub. If register bean definitions by configuring base-packages, may end up with many unused Stubs and FutureStubs. If these bean definitions are set to Lazy Init, it’s not a big issue (as beans won’t actually be created).

Also creating beans at that point in time may break many assumptions (conditions, etc).

I understand your point. I think you are right. Doing it this way can indeed break many things.