Spring Instantiation and 'unused beans' - spring

I'm working on a project which means customising an existing application (JasperServer 3.7.1) which is implemented in Spring 2.5.6 (plus a host of other Spring frameworks).
The application consists of a host of applicationContext*.xml containing the bean definitions which when wired together by Spring bring the app to life - I think it's a typical Spring app configuration as although it my first experience using Spring, it seems all quite well put together and follows a lot of the examples I have seen on the web and in books..
Because I'm actually modifying an existing application, changing beans like filterChainProxy (because we have our own security model ,for example) I'm wary of changing the actual config files that come with the product - instead, where possible, I'd prefer to add extra appContext config files to the existing ones which override existing beans (ie leave the original config in tact, as much as possible).
This I've managed to do by creating beans implementing BeanFactoryPostProcessor which on pre-bean initialisation allow me to change the existing property values/bean references to custom ones. This all seems to be working fine.
My query is, say I had a bean with a property that referred to another bean, and my overrider bean changed that reference to my own version of bean, will Spring still instantiate the bean that is no longer referred to ? The reason for asking obviously is that some of these unused beans may be taking up resources, which may be an unwanted overhead.
Thanks in advance

I'm not sure I follow your example, but it might help to clarify a few things.
Generally, Spring will instantiate a bean for every non-abstract bean definition in the context (this is ignoring things like non-singleton bean scopes, but I'll ignore that for the purposes of this explanation). If multiple bean definition files are used, and some bean names are duplicated, then some definitions will be overridden by others. so far, so good, this seems to be what you wanted.
Once the bean definitions have been established, and any duplicated dealt with, then Spring will then instantiate a bean for each of those definitions. If you have changed the definition of BeanA so that it no longer refers to BeanB, but instead refers to BeanC, but the definition of BeanB still exists, then BeanB will still be instantiated, even if it's not being used.
If that example is not representative of your question, then please elaborate.

Related

why #RestController by default use singleton scope?

I am actually a EJB developer and very new in spring framework.
i find a couples of conflict conceptually. Like ..
#RestController use by default scope which is singleton. By single object per loc have to manage heavy trafic.
is it a good design?
Of course, it is a good design because the same instance of the object will be reused instead of keep creating it each time you need it. That is the whole point of that design pattern.
Here is a great example where singleton comes to the rescue.
https://rules.sonarsource.com/java/RSPEC-2119
By default, spring will take care of the creation and destruction of all singleton beans, while the prototype has to be manually handled. Therefore in a lot of cases prototype scope is for custom beans made by developers.
In SpringMVC Controller layer, #Scope("prototype") vs #Scope("singleton")
is it a good design?
Yes, all beans in Spring are singletons (by default).
We have 100+ controllers in several applications and it works perfectly.
If you really need to instantiate controllers more than once, you can, of course, consider other bean scopes (see brief explanation of scopes here https://www.baeldung.com/spring-bean-scopes)

How to provide custom logic to search for bean if it cannot be found in Spring Context

If the Spring context cannot find a bean referred to from my xml I want to be able to provide some custom logic (ie look in another Spring Context or create the bean programmatically) before a BeanNotFoundException (whatever the expection is) is thrown.
You can use the BeanFactoryPostProcessor to define your beans dynamically (click on the link for an explanation).
Alternatively if you want to act on your bean in a lazy manner (instead of at app startup), which I strongly recommend not to do since you will have bugs related to the state of you beans config that is not visible at compile time: Anyway, you can surely add to your ApplicationContext a custom singleton : instead of calling getBean() from spring, if nothing was found, your class will be called to respond which bean corresponds to a bean name, and you will indirectly have the opportunity to handle BeanNotFoundException
See a post about the second (not recommended) solution here : How to add Properties to an Application Context

Does ComponentScan order matter?

I'm setting up a very small Spring/REST/JPA project with Boot, using annotations.
I'm getting some Bean not found errors in my REST controller class that has an Autowired repository variable, when I move my JPA repository class out to a different package, and calling componentscan on its package. However, everything was working fine when all my files(5 total) were in the same package.
So I was wondering, however unlikely, if the component scan order matters? For example, if a class is AutoWiring some beans from a package that has not been 'component scanned' yet, will that cause a Bean not found error?
No, Spring loads all configuration information, from files and annotations and the environment when appropriate. It then creates beans (instances of classes) according to a dependency tree that it calculates in memory. In order to do this it has to have a good idea of the entire configuration at startup. The whole model derived from all the aggregated configuration information is called the Application Context.
In modern versions of spring the application context is flexible at runtime and so it's not quite the case that all the configuration is necessarily known up front, but the configuration that is flexible is limited in scope and must be planned for carefully.
Maybe you need to share some code. When you move that stuff, you also need to tell Spring where they went. My guess would be you haven't defined #EntityScan and #EnableJpaRepositories (which default to the location of #EnableAutoConfiguration).
There could be several problems:
You moved your class out of the some package where you have #ComponentScan without arguments. That basically means that components are scan only in this package and its children. Thus, moved class are not scanned and there is no bean to wire.
Wrong package name in #ComponentScan args.
The order isn't matter at all. There is an #Order annotation, but it's purpose is more about loading multiple implementations of sth in a different order.
At first Bean Definitions are created and they have nothing to do with wiring. Then via bean post processors, autowired beans are injected. Since there were no bean definition. There is nothing to inject.
In a well structured program it doesn't, because first each bean gets instantiated, then autowired and then you can actually use them.
However there could be situations where the order does matter and I had an issue figuring out what was going on. So this is an example where it would matter:
You have some Repository that you want to fill with data initially, call it SetupData component.
Then you use #PostConstruct to save the default objects.
You have some component that this Repository depends on but isn't managed by Spring, for example a #Converter.
And that #Converter depends on some other component which you would statically inject.
In this case #PostConstruct methods will be executed before the components into your #Converter get autowired which will result in an exception.
Relying on ComponentScan order is a bad habit, because it's not intuitive especially when you are working with multiple people who may not know about. Or there might be such dependencies that you can't fix the code by changing the scan order.
The best solution in this case was using a task executor service that takes care of running initialization functions.

Use/Purpose of beans in Spring

Could someone give an overview or a summary of what the purpose of beans in a Spring framework context?
I understand the standard Java bean (no arg constructor, getters/setters, often serialized), but the Spring bean purpose seems to be different.
Is it a way of implementing the Singleton design pattern (one instance, for like factory classes) in a simple, reusable fashion?
I've mainly used Spring with annotations, but I feel I need to grasp this in order to understand Spring.
Thanks!
Beans are objects that form the backbone of the application.
A bean is simply an object that is instantiated, assembled and otherwise managed by a Spring IoC container; other than that, there is nothing special about a bean.It is in all other respects one of probably many objects in your application.
Spring beans are defined in a spring configuration file or by using annotations, instantiated by the Spring container, and then injected into your application.
Spring beans will not be singleton design pattern until you explicitly make them to be.The singleton design pattern and the spring scope 'singleton' are different things.You can define different bean scopes depending on your requirements.
The scopes could be :
singleton – Return a single bean instance per Spring IoC container
prototype – Return a new bean instance each time when requested
request – Return a single bean instance per HTTP request.
session – Return a single bean instance per HTTP session.
globalSession – Return a single bean instance per global HTTP
session.
The default scope is singleton.
I understand the standard Java bean (no arg constructor,
getters/setters, often serialized), but the Spring bean purpose seems
to be different.
You mean always serialized. Why do you think the purpose seems different?
In the end, you write classes. A lot of time these are POJOs, Plain Old Java Objects. Sometimes you implement an interface or extend a class, but its all just classes.
Beans are just classes. Don't overcomplicate it.
Now Spring might take your beans (classes) and manage them for you via any of a number of policies (prototype, singleton) but that doesn't change what a bean is, it speaks to how Spring manages the bean.
To understand best, you should get familiar with dependency injection. In a few words dependency injection allows you to use objects, or services without explicitly creating them (of course, it gives other benefits, but let's focus on the question). This is achieved by maintaining a dependency container that is - roughly said - a collection of beans.
A bean is a service/component you use in your application. Unlike the EJB, with Spring the bean is not constrained to constructor arguments or specific annotations (especially if you use xml contexts). You register a bean with a container (by defining a context), and when you require it, the container will provide you with an instance of that bean. In order to create the bean, the container examines its class and constructors, and uses any other registered beans within that context, to call the appropriate constructor or property setter.
You can configure a bean to be a singleton - this is not a singleton as in the design pattern term. Singleton beans are created once within the container, and the same instance is used whenever the bean is requested from that container. You can also use the prototype scope to force the container to create a new instance each time.

Does spring internally do a getBean on the property refs it needs to load?

When i want a bean say in the main method I ask for a getBean on the id. Does spring container do the same when we define properties as refs to other beans within a single bean ?
Does spring container do the same when we define properties as refs to
other beans within a single bean
Ultimately yes, Spring does find beans within the application container which match your bean definition. How it does it is something which shouldn't be too much of a concern to most users. Since it's usually enough to know that if you ask for a bean from Spring it'll come wired with all of it's dependencies.
If you're interested in the exact wiring mechanism the source code is the place to learn.

Resources