I'm using ListableBeanFactory to fetch beans that match specific annotations. While this works, the performance is low. Also, I also know the set of classes which will contain the annotations. It seems the ListableBeanFactory is searching all the beans. How do I tell it to search only a small subset of classes so that I can improve the performance?
Generally speaking this spring feature does not perform well in the real-time repeating tasks. Try to fetch these annotated beans during the startup and then access them. Or just don't use Spring for this particular case. Another way is to use child context instead of main Spring context: you can create additional child context containing beans from the specific package or just the specific beans, they will still be able to resolve their dependencies from parent context but not vice versa.
Related
I’m taking this udemy course all about Spring Hibernate etc. The course started with explaining how Injection of Control and dependency injection works not in a web perspective just like having simple classes or beans, defining beans and their dependencies inside a config xml file or inside the actual class Using java annotation and then a main class where the beans are created. I understood that despite not really seeing the big benefit of using IoC and DI other than separating roles like creating and maintaining objects and adding dependencies the object needs and I guess when the project is bigger this makes it cleaner and easier to follow right?
However what I don’t understand is how IOC and DI ties in a full spring MVC project. Like I understand using the #Controller annotation means it’s like an #Component and you could make it scan the components automatically when it creates beans but like unlike before there isn’t a main class where beans are created and configured rather I have a controller class where I manually create objects and models and pass that back to the views where I can use the values in the model. I don’t see how I use IoC or DI here? Or is it because it’s a simple project and perhaps the objects we created didn’t have many dependencies?Or are a lot of the uses and implementation done internally or automatically?
I am just struggling to a) see why IoC and DI are that important and b) how are they actually used in a Spring MVC project where you don’t have a main class where you do create beans.
A) Create a project, but don't add any dependency (or web-mvc). Then do it yourself then see how much need time to create configure manually. If it is just a simple mvc project, you can do it manually, but if your project increase day by day then a huge configuration file to maintain your project properly. But when you are professional developer, you don't have so much time to configure all those manually. So here is come the solution IoC and DI. Controller or other anotation are configured in build-in jars. You don't have to worried about to create controller or to create bean, just use them when you neer them. It's save your time as well as headache about is it working or not. It's increase your productivity while your are working on a big project.
B) Yes, there is no main class in web project. To run a web project, you need a server. The server first looking for a configuration (In spring, it's web.xml, dispatcher-servlet). If it available then expand the configuration file, if not then throw an error. In that configuration file, explain everything about the web project. What should do, what is not mandatory, what is entry point etc.
So, IoC and DI are very important because to understand how a web project work behind the scene or how all component work together.
IoC is a process whereby objects define their dependencies, that is, the other objects they work with, only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse, hence the name Inversion of Control (IoC), of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes, or a mechanism such as the Service Locator pattern.
In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application.
The advantages of this architecture are:
decoupling the execution of a task from its implementation
making it easier to switch between different implementations
greater modularity of a program
greater ease in testing a program by isolating a component or mocking its dependencies and allowing components to communicate through contracts
Inversion of Control can be achieved through various mechanisms such as: Strategy design pattern, Service Locator pattern, Factory pattern, and Dependency Injection (DI).
You can go with Annotation based configuration, where you can define #Configuration class and return the required beans using #Bean annotation.
Also you can use #Component to your POJO class to treat it as Spring bean.
Is creating objects by hand, i.e. using new operator instead of registering Spring bean and using dependency injection considered bad practice? I mean, does Spring IoC container have to know about all objects in the application? If so, why?
You want Spring to create beans for classes that :
you want/need to inject instance(s) in other beans
you need to inject beans (or dependencies) in their own instances.
you want them to benefit from Spring features (instantiation management, transaction management, proxy classes Spring empowered such as Repository/Interceptor and so for...)
Services, controllers or interceptors are example of them.
For example a controller may need inject a service or an interceptor.
As well as you don't want to handle the instantiation of these classes by implementing yourself the singleton pattern for each one. Which could be error-prone and require boiler plate code.
So you want all of these classes to be beans managed by Spring.
But you don't want to Spring create beans for classes that :
you don't want/need to inject instance(s) in other beans
you don't need to inject beans (or rdependencies) in their own instances
you don't need them benefit from Spring features
Entity, DTO, Value Object are example of them.
For example an entity never needs to be injected into another entity or in a service as a dependency because entities are not created at the container startup but are generally created inside a method and have a scope limited to the methods lifespan.
As well as you don't need Spring to create instances which the lifespan is a method. The new operator does very well the job.
So defining them as bean instances makes no sense and appears even counter intuitive.
Spring implements the Dependency Injection pattern. You should inject in the container of spring the beans that are going to be used in other classes as dependence to be able to work. Usually classes that implement interfaces are injected so that if you change the implementation, the classes that use that interface do not know about the change.
I recommend you read the post about the dependency injection of Martin Fowler.
Using new is not bad and you are just giving the IoC container the responsibility of using new under the hood. IoC will know about all the classes that you register with it. When using frameworks, it's even more important to think about the applications architecture, because a framework makes bad design as easy to implement as good design.
If you don't need multiple implementations of a class, then use new.
If you think it's plausible that you may need to switch between implementations, consider your app design and find a suitable injection point so that refactoring won't be such a drain.
If you need multiple implementation of a class, then use a design pattern like a factory or a DI framework.
Not every nook and cranny of an application needs to be highly configurable. That's what leads to over-engineered and hard to maintain code.
I'd like to extend usage of CDI in the app I develop. What I need is something like application context/scope but I need to handle multiple instances of beans based on how many records are in the database/configuration.
To be more specific, in our database, there's a table called PODs and for each record in this table, I need a separate group of beans (services, repositories, etc. - a whole object graph). There's no need for dynamic behaviour - it's OK to restart application when a record is created/deleted in this PODs table. But ideally items defined within this PodContext for a specific POD should be able to inject beans within the context of the same PodContext.
The obvious problem here is how to specify for which POD a bean instance should be created/injected.
That leads me to a question if a custom CDI context is actually suited for such a use case but without losing all the CDI goodies and building all the object graphs manually, I don't see a good way out :(
Update: My colleague suggested a solution for Spring Framework - we could have a parent context with all the shared application-wide beans, and also one child context for each POD, which would define beans for that specific POD. It's possible because Spring allows such context hierarchies. Is there anything similar in CDI?
I am developing Spring mvc application.
I have a controller in which I am injecting more than 10 Services.
I am exposing 10+ url from this controller and at a time I am using one or two service objects in each method.
I was thinking of 2 approaches.
Directly inject all services using #Autowired.
Fetch Service from ApplicationContext at runtime whenever required.
Please suggest me which approach is better or both approach are equal in terms of memory usage and time
Thanks
The best approach in most cases is to break up the controller into multiple controllers.
Having too many dependencies is a Code Smell since your controller most likely violates the Single Responsibility Principle.
Both using #Autowired for many dependencies and using the ApplicationContext to dynamically retrieve the dependency are mediocre solutions in most cases and should be avoided whenever possible. What you should do is break up the controller and then use #Autowired (preferably constructor rather than field injection - check out this for more details) to make Spring inject the dependencies.
In the case you describe you should not be worried about the performance or the memory consumption of your proposed solutions, but the maintanability of the code.
Although dynamic lookup of a dependency from the ApplicationContext will be a little slower that accesing the injected by the container dependency, in almost all cases you we never be able to tell the difference. As I mentioned above, the first concern you must be looking at is code maintanability, not micro-performance/memory issues.
I asked a question yesterday ( Using Spring in standalone apps ) on how you would use Spring in a standalone application. From that I learned that you only create the application context object once. So now the question is (even though it was partially answered in a comment) what happens when you create the application context?
Does Spring create the beans and wire them together when you say
new ClassPathXmlApplicationContext("some.xml") ?
I am not sure if I understand the boot strapping, and why it is like that.
The idea behind the ApplicationContext in Spring is that in order to properly inject objects where they are needed, some thing needs to be aware of the configuration the user specifies and inject dependencies based on this configuration.
The ApplicationContext is the thing that understands the user's wishes in terms of where and what should be injected (as well as other things such as AOP pointcuts and such) based on the configuration a user provides, either through an xml file or annotations.
Yes it will parse the bean definition file , it will create the beans , give them the dependencies,
The easiest way to debug is to go with the output print statements,
Put the statements in constructor & setter methods and try different possibilities to track the flow