I am trying to understand how beans that we make using #Configuration tends to override the beans that are generated by SpringBoot by default. I have been working on a project where in many cases we create beans for things like ZuulConfigs and the assumption is, whatever we are making shall take precedence over the default generated bean. I have been trying to figure this out but can't. Basically,
Is Spring achieving this via some custom class loader
If not how is this precedence working. Can I give some precedence in similar manner to my beans
Can I generate similar hierarchy in my project,if so how
The help is highly appreciated
Spring AutoConfiguration is used to provide a basic configuration if certain classes are in the classpath or not.
If you want to configure the order in which beans are instantiated by spring you can use
#DependsOn("A")
public class B {
...
}
This would create bean "A", then "B". Hence you can order the configuration depending upon the beans need first to be done. Anyways Spring automatically detects the dependencies by analyzing the bean classes.
for more help check this question
Spring Boot AutoConfiguration Order
Alternative :
There is also "#AutoConfigureOrder" annotation(where you can prioritise the configuration), you can have a look in the code for deeper understanding.
Documentation of AutoConfiguration is here
First of all, class loading and bean creation are two different things. We don't need to create a bean to load a class, however, a class has to be loaded in order to create a bean.
Now, coming back to Spring's example, Spring looks into all the packages configured by #componentScan and creates beans of all the classes annotated with #Bean, #Configuration and/or #Component. Spring's container keeps track of all the beans created and hence, when it encounters user defined bean with same name and class type as default bean, it replaces the original definition with user defined one (e.g. we can create our custom #ObjectMapper to override Spring boot's own instance). You can also use #Primary annotation to make you bean take precedence if another definition with same class exists (documentation here).
Below are the answers for your questions:
Spring uses reflection to load the classes and create instances. Although you can load the classes with your custom class loader (more on that here), you don't need to worry about it for #Configuration.
Yes, you can use #Primary annotation to give your bean a precedence. You can also use #Order(here) to define the creation order for your beans.
With #Primary, #Order and #Qualifier annotation you can define your own hierarchy for bean creation.
Can I give some precedence in similar manner to my beans
Yes.
A) To define a specific order your Configuration classes will be handled (by the way, a Configuration class does not have to be annotated with #Configuration (so-called full definition), but it's enough to be annotated with #Component, #ComponentScan, #Import, #ImportResource or just have a method annotated with #Bean - so-called lite definition), you should
1) add your Configuration Candidates to your SpringApplication's primarySource, for example, in your main method like that
SpringApplication.run(
new Class[]{YourSpringBootApplication.class, Config1.class, Config2.class, ...},
args);
2) and annotate each of your Configuration Candidates with #Order annotation, any other ordering means like Ordered interface, #DependsOn etc will be ignored by ConfigurationClassPostProcessor, the order in the primarySource array will also be ignored.
Then ConfigurationClassPostProcessor will sort your Configuration Candidates and handle them according the #Order annotation value you specified.
B) The precedence can also be achieved by defining your own AutoConfiguration classes. Although both Configuration and AutoConfiguration are handled by the same ConfigurationClassPostProcessor, they are essentially distinctive machineries. To do so
1) define in your classpath /META-INF/spring.factories file and put in the EnableAutoConfiguration section of it your AutoConfiguration classes like that
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
your.package.AutoConfig1,your.package.AutoConfig2
2) and annotate your AutoConfiguration classes with #AutoConfigureOrder, #AutoConfigureAfter, or #AutoConfigureAfter annotations, any other ordering means again will be ignored.
Like #Strelok pointed out, AutoConfiguration classes, your own and provided e.g. by spring-boot-autoconfigure library alike, will be added to the end of the list of Configuration Candidates.
Remember, however, that the order the Configuration Candidates will be handled by ConfigurationClassPostProcessor does not necessarily coincide with the order the beans defined by the Configuration classes will be created. For example, you might define your Configuration class that overrides TomcatServletWebServerFactory to make your own customization of Tomcat web server like
#Configuration
public class EmbeddedTomcatConfig {
#Bean
public TomcatServletWebServerFactory containerFactory() {
...
return customizedTomcatWebServerFactory;
}
but this method will be called right at the moment when your Spring Boot application decides to create a Web server, regardless of how you defined the precedence for your EmbeddedTomcatConfig Configuration class.
Is Spring achieving this via some custom class loader
There is no need to. Although you could, as always with Spring, define your own ClassLoader for BeanFactory, standard ClassLoader is good enough if everything you need for Configuration in your application is available in the classpath. Please notice, that at first phase ConfigurationClassPostProcessor does not load (i.e. does not resolve) the Configuration candidates classes (otherwise, most of the classes in spring-boot-autoconfigure library will fail to load). Instead it analyzes their annotations with bytecode analyzer, ASM by default. For that purpose, it is just enough to get a binary form, a byte array, of a class to feed it to bytecode analyzer.
Just know this: Spring Boot (specifically) auto configuration classes are always configured last. After all user beans have been created. Spring Boot auto configuration classes almost always use the #ConditionalXXXX annotations to make sure that any beans of the same type/name and other conditions that are configured in your application will take precedence over the Spring Boot auto-configured beans.
If you want your #Component to take precedence over other #Component while scanning all the components by spring, use #Order(Ordered.LOWEST_PRECEDENCE) i.e. the max value to load your component over other.
#Primary is used to give your bean a default preference, we can override the default preference using #Qualifier
Related
I have been given a task to assign a property from .properties file to a non Spring bean class using #Value annotation. To do this, I created a method on a #Component annotated class and set the property into it, then called that method from the non Spring bean class. I thought this would work, however, still showing as null.
I was told this is because the #Component annotated class I used is not spring loaded. Question, how can I tell if a class is Spring loaded bean? I have been searching on google but can't find anything helpful aside from examples with #Component or #Configuration annotations. Thanks.
Spring Container is responsible for creating or managing beans. It all satisfy the dependencies by injecting them either through constructor or setter method. But in your case you want the #Value injection in your non spring bean which is really not possible as per my understanding. Because here the spring does not creating the object then how it satisfy the dependencies of it.
You have two options for this situation.
Either annotate class using #Component
Either read property file using Properties
https://www.mkyong.com/java/java-properties-file-examples/
Problem context: in our application we use custom PropertySourcesPlaceholderConfigurer to extend possibilities of EmbeddedValueResolver with custom property sources. I am very inspired of Spring Boot #ConditionalOnProperty and #ConditionalOnExpression and want to use it with custom placeholders.
What I wanted to do was to write custom #Conditional annotation that uses EmbeddedValueResolver to resolve placeholders (${...}). I noticed that ConfigurationClassPostProcessor implements ResourceLoaderAware interface, and ResourceLoaderAware classes are configured later than EmbeddedValueResolverAware ones. So when we initialize ResourceLoaderAware, our EmbeddedValueResolverAware beans are already configured. So potentially solution seems possible.
What I wanted to do next was to write custom Condition that uses EmbeddedValueResolver from ApplicationContext to resolve some property and match it to some value. But the problem is that Condition uses some another context class called ConditionContext which doesn't include EmbeddedValueResolver. Using Environment#resolvePlaceholder doesn't help - seems like Environment doesn't know anything about placeholders that are available through EmbeddedValueResolver.
So, is that possible to use EmbeddedValueResolver with Spring conditionals?
I encountered this issue when I'm trying to override the RibbonRoutingFilter bean defined in spring zuul. To emphasis, I'm doing an override, not just creating a bean of the same type. So end of the day, I want the "ribbonRoutingFilter" bean from zuul not registered at all.
So I have my own implementation. First thing I tried, I used the #component annotation and autowire the dependencies. Added a breakpoint in the constructor, and it ended up never being called. So I realize my definition must be loaded earlier than zuul's. So I created a configuration class with #Configuration annotation and #Order(Ordered.HIGHEST_PRECEDENCE), and use a #Bean annotation to instantiate my class there. Still, my method is always loaded earlier.
It turned out there's certain order Spring is following when loading configuration classes definitions and that is where overrides happen. Class org.springframework.context.annotation.ConfigurationClassParser has the detailed logic in method doProcessConfigurationClass(). I'll put my simplified summarization or the ordering rule here:
if you application class(where main() method is defined) has any classes defined in it, they are parsed and definition inside them are registered first
then it will registered Beans defined as #component and defined in #Configuration class
then it will add definitions introduced by #Import
then it will add definitions introduced by #ImportResource
then add definitions from #bean methods inside the application class
then from default methods on interfaces( I think it's java 8)
then try to do the same steps above for any parent classes you application class has extended.
This explained why my override was not working. It's because all I have been trying is in step 2. But zuul defined the bean by a #Import which is step 3.
So to solve my problem, I added a #Bean annotated method to my application class there and do the instanciation and the override just happend as expected.
The above summarization might not be accurate, it just give you an idea about what could have failed your override. You'd better debug the ConfigurationClassParser when you are trying your specific use case.
How to enable the #Required annotation in Java (Spring 3.1) ? Not in a xml, but in through Java. Also under which annotation I put this enabling? Under #Feature (in #FutureConfiguration or #Bean (in #Configuration) ?
Edit:
#Feature
public MvcAnnotationDriven annotationDriven(ConversionService conversionService) {
return new MvcAnnotationDriven().conversionService(conversionService)
.argumentResolvers(new CustomArgumentResolver());
}
Does this enables all annotations?
#anubhava's answer works, but he's referenced the Spring 2.0 manual, which is 5 years old.
In XML config, Spring 3.x has a more elegant approach: <context:annotation-config/>. This also enabled a whole other bunch of features that you'll probably want, whereas RequiredAnnotationBeanPostProcessor only enables a few.
See Spring 3.x manual.
If you're using #Bean-style config, then annotations like #Required should already be enabled, since that's how #Bean works. However, it's possible that this is a bug - Spring 3.1 is still in early beta, and big chunks of it are likely to be broken.
Unless you really know what you're doing, I strongly recommend sticking to 3.0.x.
From the Spring manual:
There is one last little (small, tiny)
piece of Spring configuration that is
required to actually 'switch on' this
behavior. Simply annotating the
'setter' properties of your classes is
not enough to get this behavior. You
need to enable a component that is
aware of the #Required annotation and
that can process it appropriately.
This component is the
RequiredAnnotationBeanPostProcessor
class. This is a special
BeanPostProcessor implementation that
is #Required-aware and actually
provides the 'blow up if this required
property has not been set' logic. It
is very easy to configure; simply drop
the following bean definition into
your Spring XML configuration.
<bean class=
"org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
Please check: http://static.springsource.org/spring/docs/2.0.x/reference/metadata.html
Use AnnotationConfigApplicationContext if you don't want to use XML:
Standalone application context,
accepting annotated classes as input -
in particular #Configuration-annotated
classes, but also plain #Components
and JSR-330 compliant classes using
javax.inject annotations. Allows for
registering classes one by one
(register(java.lang.Class...)) as well
as for classpath scanning
(scan(java.lang.String...)).
In case of multiple Configuration
classes, Bean methods defined in later
classes will override those defined in
earlier classes. This can be leveraged
to deliberately override certain bean
definitions via an extra Configuration
class.
Sample Code:
ConfigurableApplicationContext applicationContext =
new AnnotationConfigApplicationContext(
"com.mycompany.package1",
"com.mycompany.package2",
"com.mycompany.package3"
// etc.
);
applicationContext.refresh();
I am learning java for 3 months and sometimes
i can not understand the usage purpose of something.
one topic was dependency injection and spring beans i figured out the finally =)
now i confused with the two annotations #Autowired and #Repository.
First What does Autowiring mean? then
Why should i use them and what is the difference between using them and not using?
Also today i tried to use hibernate in a spring mvc project and i had to search for about 15(cause of class not found errors) jar files beacuse of the dependencies of other jar files used in the project.
is this had to be this way? this makes learning java very hard for the beginners
thanks...
#Repository is an annotation that marks the specific class as a Data Access Object, thus clarifying it's role. Other markers of the same category are #Service and #Controller
#Autowired is an annotation with a completely different meaning: it basically tells the DI container to inject a dependency. More info at http://apollo89.com/java/spring-framework-2.5.3/api/org/springframework/beans/factory/annotation/Autowired.html
Edit
More info at tutorialpoint
or docs.spring.io
Both the annotations have different purposes to be used.
#Autowired: This is same as <bean="xyz" autowire="byType"> you define in the configuration file. The reference variable (dependency) that is annotated with #Autowired, will be injected by Spring container as any matching #Bean found in #Configuration class.
Plus the classes annotated with #Component, #Service, #Repository are too considered as beans so their objects are injected into the matching dependencies.
Spring container scans the beans in the classes you mentioned for "component-scan" or #ComponentScan("xyz").
#Repository: This is also a spring-framework's annotation. When you annotate a class #Repository, spring container understands it's a DAO class and translates all unchecked exceptions (thrown from DAO methods) into Spring DataAccessException.
DAO class is the class where you write methods to perform operations over db.
#Autowired and #Repository are very 2 different concepts.
1.# Repository: This define a class to be a repository, In general term you can use simply #Component but to define specifically, there are 3 more annotations like Controller,service and repository.Mainly 2 advantages:
1.If you have defined(context:component-scan)in servlet.xml to scan the defined package and find its own by spring.
2. More advantages you get from spring like database access error translation, so it is mainly defined to use with class in which you are connecting with database either with hibernate or jdbc.
#Autowired: to inject dependency at run-time by spring, means in a class, autowire a object ,and use it ,so this bean will automatically be made without defining in xml file