I am looking into a codebase where every POJO has been managed by spring and injected using lookup annotation.
#Lookup
public Publisher getPublisher() {
return new Publisher();
}
#Lookup
public Book getBook() {
return new Book();
}
These Publisher and Book objects are nothing but POJO with just getter/setters. These classes are spring managed as prototype beans. I am thinking, it is over use of lookup annotation and overhead where we could just use factory methods or simply create new instance. Do you think using lookup annotation for this use case useful/efficient?
In a general way, making instances of a class some spring beans is not relevant if these beans never be needed to take advantage of Spring features and if these beans never be injected in other beans or never needs to inject other beans in their own instance.
#Lookup is the annotation-based way of the the old XML lookup-method attribute. Besides beans created with this annotation also have multiple limitations. For new projects I never use it.
As alternative as you need to declare beans in the java class the #Bean annotation that creates "not limited" beans should generally be favored instead of.
EDIT :
I wrote an answer to a very related question yesterday : Spring - is using new a bad practice?.
I just updated it to be more exhaustive.
Related
I know that you can use the annotation #Mapper(componentModel = “spring”) to use Spring to manage/inject the mapper dependency. My question is, are there any advantages to this approach vs declaring an instance variable within the mapper class itself:
#Mapper
public interface SomeMapper {
SomeMapper INSTANCE = Mappers.getMapper(SomeMapper.class);
SomethingElse mapSomethingToSomethingElse(Something something);
}
...
// Clients using mapper
SomethingElse result = SomeMapper.INSTANCE.mapSomethingToSomethingElse(input);
When using Spring dependency injection to inject mappers, you will end up adding extra constructor arguments/instance fields which is desirable as it makes it more obvious that a class is starting to rely on too many dependencies and should most likely be refactored (eg. think about Sonar's rule 'Too many parameters').
Another advantage is that since you're registering the mappers as beans in the Spring context, you can leverage the framework capabilities to easily inject dependencies in your mappers, customize all mappers at runtime through the BeanFactoryPostProcessor and rely on all the other framework abstractions that seem fit.
I'd say since you're already using Spring in your application, there is pretty much no reason to not register the mappers as Spring beans and inject them the DI way rather than turning them into static utils.
Anyone can explain how Spring defines the bean creation mechanism when create a bean which depends on a list of other beans? It would be good to show the part of Spring specification on how it's defined.
Code like:
public interface Test {
}
#Service
public class TestImpl1 implements Test{
}
#Service
public class TestImpl2 implements Test{
}
public class TestContainer {
List<Test> testList;
TestContainer() {
testList = new ArrayList<>();
}
public void addTest(Test test) {
testList.add(test);
}
}
then
#Bean
public TestContainer testContainer(List<Test> testList) {
TestContainer testContainer = new TestContainer();
for (Test test : testList) {
testContainer.addTest(test);
}
return testContainer;
}
Question is really: when creating bean for TestContainer, how does Spring figure out what should be in List testList?
This looks like what you are looking for:
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-class
You haven't specified what exactly do you want to know about bean creation but here is the minimum you should know. By default all beans are singleton scoped (only created once during the container life-cycle and for all the subsequent request the same instance is returned). All singleton scoped beans are created eagerly. If the singleton bean is dependent on some other beans (needs them for instantiation) then those other beans will be instantiated with it/right before it, doesn't matter whether they are singletons or not, marked as lazy or not.
This is part of the spring documentation I think on their website. Look for it. The whole spring documentation is worth to read, even if it is a long read (https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#spring-core)
But mostly, spring would first read all the XML, anotations and other source of config data and get a list of beans to init. Then it would get a list of dependencies between beans constructing kind of a tree. As the dependencies need to be initialized first, there an obvious orderining for initialization.
On top, you can set your own priorities for beans so that you can get some beans initialized first or last for example.
For your specific case, spring will inspect the code source as well as use the Java reflection API to figure out you want a collection of interface Test implementations. So spring would look for ALL the defined bean that match and return them that not more complex than that.
It's mostly using the concepts of graph data structure where the beans become the nodes of the graph and they are resolved using topological sort.
I have a collection of classes which I want to be injected into the Spring application context. However, these classes can only be guaranteed to be annotated with one of a group of annotations I have written - i.e. I can assume it will be annotated with #MyAnnotation, but not #Component.
However, #MyAnnotation forms part of an API for my project, and I don't want to state an explicit dependency of this API on Spring. Thus, I can't annotate #MyAnnotation with #Component in order to have it be transitively picked up by Spring.
Is there a way to tell Spring to additionally include #MyAnnotation in its classpath scanning without adding this dependency to my API?
Currently I'm manipulating the bean definition registry to 'manually' add each class annotated with #MyAnnotation, but I'd prefer to rely on Spring's inbuilt support.
Thanks in advance.
It's possible if you create your own BeanDefinitionRegistryPostProcessor to register your own beans. If you implement the postProcessBeanDefinitionRegistry method, you can add beans to the registry by yourself, for example:
#Component
public class FooFactoryBean implements BeanDefinitionRegistryPostProcessor {
#Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
registry.registerBeanDefinition(..);
}
}
To obtain these bean definitions, you can use the ClassPathScanningCandidateComponentProvider class, which will create BeanDefinition objects for all classes found for a specific filter. In this case, an AnnotationTypeFilter will work:
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(Foo.class));
Set<BeanDefinition> definitions = scanner.findCandidateComponents("com.example.my");
In this example, it will find all classes annotated with #Foo in the com.example.my package.
#Configuration classes and XML based configuration should work for you. Have a look at this tutorial: https://www.tutorialspoint.com/spring/spring_java_based_configuration.htm
But to get your #MyAnnotations picked up is more difficult (see #g00glen00b's answer), and I'm not sure it makes sense if the above mentioned solutions are available.
I liked annotations used for bean declaration etc. But now we have so many beans with order (#Depends). It is tough to maintain or look at a glance the configuration.
Is there any tool that provides "Effective Spring Config" information based on all your bean annotations?
Answer: you should not be using that many #DependsOn annotations.
From the javadoc:
Used infrequently in cases where a bean
does not explicitly depend on another through properties or
constructor arguments, but rather depends on the side effects of
another bean's initialization.
You can just do this:
#Configuration
public class MyConfig {
#Bean
public MovieClient movieClient(RestOperations rest) {
return new MovieClientImpl(rest);
}
#Bean
public RestOperations restOps() {
return new RestTemplate();
}
}
In this example, the RestOperations bean will be instantiaded before the MovieClient bean, just because the movieClient bean asks for it in the constructor. You don't need any #DependsOn annotion in cases like this one.
Edit: as OP commented, there is still the issue of showing the "Effective Spring Config".
I do not think there is any tool for that, because your dependencies may change at runtime (because of AutoConfiguration, #Conditional annotations, profiles, other?).
If you need to know your "Effective Spring Config" (i.e. "what beans are present at runtime"), you can do this:
ConfigurableApplicationContest context;
context = SpringApplication.run(Application.class, finalArgs);
// Print all the beans:
System.out.println(context.getBeanDefinitionNames());
However, if you meant how can you view and navigate all the configuration, you can organize your beans in different #Configuration files, pick them up using #ComponentScan, and navigate them using the Spring IDE pluguin for Eclipse, like this:
I have a POJO class with a method annotated with #Transactional
public class Pojo {
#Transactional
public void doInTransaction() {
...
}
}
Spring declarative transaction management is based on AOP but I don't have any experience with that. My question is:
Is it possible that when invoking the (new Pojo).doInTransaction() alone, Spring will start a Transaction.
Spring declarative transaction
management is based on APO but I don't
have any experience with that.
I would recommend to start working with it and you will get the experience of using transaction advices using AOP. A good starting point is here.
Is it possible that when invoking the
(new Pojo).doInTransaction() alone,
Spring will start a Transaction.
No, you can't expect Spring to be aware of a bean that you manually invoked. However, it sounds like that you are wanting to avoid declarative transaction management and do programmatic transaction management. There is a way to do that with Spring using the Transaction Template. Is that what you were looking for?
It is somewhat possible, but in a cumbersome way: You must use the AutowireCapableBeanFactory mechanism.
Here is a transactional class as example
public interface FooBar{
void fooIze(Object foo);
}
public class FooBarImpl implements FooBar{
#Transactional
#Override
public void fooIze(final Object foo){
// do stuff here
}
}
And here is how we can use it:
public class FooService implements ApplicationContextAware{
private ApplicationContext applicationContext;
#Override
public void setApplicationContext(
final ApplicationContext applicationContext){
this.applicationContext = applicationContext;
}
public void serviceMethod(){
//declare variable as interface, initialize to implementation
FooBar fooBar = new FooBarImpl();
// try to use it, won't work, as it's not a proxy yet
Object target = new Object[0];
fooBar.fooIze(target); // no transaction
// now let spring create the proxy and re-assign the variable
// to the proxy:
fooBar = // this is no longer an instance of FooBarImpl!!!
(FooBar) applicationContext
.getAutowireCapableBeanFactory()
.applyBeanPostProcessorsAfterInitialization(fooBar,
"someBeanName");
fooBar.fooIze(fooBar); // this time it should work
}
}
This is not a best practice. For one thing, it makes your application highly aware of the Spring Framework and also, it violates the dependency injection principles. So use this only if there is no other way!
Yes, it is possible. Spring does not require the use of dynamic proxies for #Transactional to work. Instead, you can use "true AOP", as provided by AspectJ.
For the details, see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-declarative-aspectj
The way Spring handle the transaction through Annotation is using AOP as you've said.
The AOP bit is implemented using Dynamic Proxies (see doc)
So in order to do so you'll need to retrieve an instance of your class (Pojo here) through the spring container since to make it work, Spring will return you a Dynamic Proxy over your Pojo that will automatically surround any annotated method with the transaction management code.
If you simply do a
Pojo p = new Pojo();
p.doInTransaction();
Spring doesn't have any role to play here and your method call won't be inside a transaction.
so what you need to do is something like this
ApplicationContext springContext = ...;
Pojo p = (Pojo) springContext.getBean("your.pojo.id");
p.doInTransaction();
Note: this is an example, you should prefer dependency injection instead of retrieving your bean manually from the context
By doing so, and with a properly configured Spring Context, Spring should have lookout your classes to scan for transactional annotation and automatically wrapped your beans into annotation aware dynamic proxies instances. From your point of view that doesn't change anything, you'll still cast your object to your own Classes, but if you try to print out the class name of your spring context Pojo bean, you'll get something as Proxy$... and not your original class name.
Have a look at this link anyway : link text