Is there any way (existing framework) to configure DI in Java without having to add annotations to classes where they "don't belong"?
In my research, it looks like to accomplish constructor injection we need to add some annotation to the constructor, like this:
#Inject // or #Autowired for Spring Boot
public MyInjectedClass(IThing1 thing1, IThing2 thing2) { ... }
Spring Boot also suggests adding #Service to implementations in order to register them with DI for injection.
Adding these annotations brings DI into the injected class (MyInjectedClass and any controllers, service implementations, etc.). Those classes should have no concept of DI, they should just be given the things they ask for in the constructor and not care about how they got there.
I know you can use the #Configuration attribute in Spring Boot, but this still feels not very configurable or powerful. Is there any way to accomplish this using Java without annotations? E.g. like how SimpleInjector, AutoFac, etc. work in C#? (Configured via code, not XML or config files, and not via annotations.)
If not, I'm curious why such a different approach has been taken between Java and C# in regard to DI.
Update I've offended someone in the comments but that was not my intent at all. I am asking a legitimate question. Let me highlight my concern/question in another way.
Suppose I have the following packages/classes. I have marked each case where each type of DI will appear. By "appear" I mean these marked classes/packages have some relation to the DI framework being used.
[A]: annotation-based DI (3rd party package dependency)
[C]: configuration-based DI
data_access [A]
repositories
PersonRepository [A]
logic [A]
people
CreatePersonCommandHandler [A]
UpdatePersonCommandHandler [A]
services [A] [C]
controllers
PersonController [A] [C]
I hope this helps to illustrate my true question. The footprint of annotation-based DI extends into the far reaches of the stack, whereas configuration-based DI is only used in the outermost (entry) application, where the composition root lives.
Related
I've a newb to Java coming from C++ / C#.
My project is currently set up like this:
org.blah.config
HibernateConfig.java
org.blah.customer
Customer.java
CustomerController.java
CustomerService.java
HibernateConfig sets up the hibernate stuff and exposes the LocalSessionFactoryBean bean.
CustomerController is the REST entry point, it doesn't really have much logic, it sort of just wraps the CustomerService.java (or should I call it CustomerRepository?).
CustomerService.java (or CustomerRepository?) wraps the DB stuff. This is where I have:
#Autowired
private SessionFactory sessionFactory;
In my CustomerController, if I do:
private CustomerService customerService = new CustomerService();
it doesn't inject the sessionFactory.
From some samples I've found, people seem to create a CustomerService bean inside of HibernateConfig and then inject that into the constructor of the controller. Is that a good practice? Would I then rename my HibernateConfig to something more specific like CustomerHibernateConfig, etc.
Just trying to get an understanding of how/where to put the config & create the service / repo instance so it can be injected into the controller.
This is quite a hard question to answer in a few words. You are asking for a whole architecture that will depend a lot on the chosen design pattern, but considering you have controllers and services, let me put it this way. MVS is just a simplification and it's not a perfect approach. This will raise so many more questions like.
How much logic should go into a controller?
Should a model contain any logic?
Should a view contain logic?
Questions like these are very hard to answer, since these are very subjective. Still, I have been using Spring for a while and will give you my advise.
The controller's function is to validate inputs and a redirect to views when needed or to respond to clients' requests. If you got domain logic (aka business logic, business rules, and domain knowledge), the logic that makes business-critical decisions, then it shouldn't be on the controller, it should be on the services.
Now, I would say that you are missing a layer on your architecture, I would definitely add a DAO, which is a design pattern that defines a way to decouple the persistence layer of your application. Which is what you would understand as a Repository.
With that said, you only need one HibernateConfiguration and do the corresponding mappings in each model or XML file related to that model. I would advise to use annotations instead of XML files.
If you want to learn how to implement a Spring project that uses Hibernate, you can see how easy it is by following this Baeldung's tutorial. That page does have the best guides regarding the usage of Spring.
I have a recurring annotation in my app that's injecting an object created by a CDI-producer.
#Inject
#FlatGeometryLive
FlatGeometry geoObject;
I wonder if it's possible to write a stereotype "#FlatGeometryLiveInject" so that i only have to write
#FlatGeometryLiveInject
FlatGeometry geoObject;
and the object is injected.
Is this possible with CDI 1.1 or any DI framework?
I don't think it's possible, because the frameworks you are using are aware, in specific point of their code, of annotations which name is Inject and FlatGeometryLive. If you define a new annotation how those frameworks could be aware, and act consequently, of your new created annotation?
In order to improve your writing productivity it's better you use your favorite IDE's hints or templates: you might create a shortcut for the text aif (Annotate with Inject and FlatGeometryLive) that your IDE will expand.
How would you extract something prior 2.5 version from .xml config? It bothers me because if #Autowired is removed from my arsenal I would not really know what to do.
Say I want to use some DAO implementation.
In service class I usually write:
#Autowired
someDaoInterface generalDao;
Then I typically call
generalDao.someInterfaceMethod(someParam param);
How would I extract implementation from config in Spring 2.0 to use this method?
Is it as dumb as just: new ApplicationContext(pathToXml) and then use .getBean or there is other way?
Why do I ask for taking bean out from configuration file?
Because in Spring MVC how can you perform your logic without getting beans out from the application context.
If you have #Controller handler then you need to make calls to the service classes' methods? So they should be somehow retrieved from the context and the only way so far is using #Autowired? Then I would also want to populate Service classes as I stated in previous example with DAO classes and they also need to be retrieved from the application context, so I would be able to write logic for service classes themself. How would people do it in the past?
I see the #Autowired as the only mean of taking something out, not because it is convenient to wire automatically - I am perfectly ok with XML.
You still have option to wire it explicitely via property or constructor parameter. (Anyway, autowired is not going to work if there is ambiguity in your container )
Of course, you can use application context and getBean() in your java code, but it violates DI pattern and makes all the spring stuff useless. Purpose of DI is to decouple your business loginc from implementation details - it's not business logic it's how and where it dependencies come from. Dependencies are just there.
By using ApplicationContext.getBean() you are breaking this pattern, and introduce dependency to:
spring itself
your configuration names
After you done this, you can as well drop use of DI and spring because you just voided all the advandages DI is providing to you. (BTW, #Autowired also introduces dependency to spring, and violates DI pattern, it also implies that there is only one instance available)
Also, answer is: in ideal case there shall be no reference to spring in your code at all.
No imports, no annotations - just interfaces of collaborating entities.
As per my understanding both Factory class and Spring DI follows the Dependency injection. I mean in both the cases external entity is used to push the dependency. Right?
My question is which one i should go for between factory classes and Spring DI when my intention is just to get the objects . Assume i don't want any other features like aop, dao support etc. Only purpose is to get the objects either from Factory class or Spring DI. Which one is preferable.
on some site read this statement
DI loosely coupled and less intrusive in comparison to Factory classes
But could not get how spring DI loosely coupled and less intrusive than factory classes?
in both the cases we have to insert some kind of get object code in our core program .
Spring DI promotes loosely coupled code because the Spring container injects your dependencies based on configuration. If you are injecting interface implementations, you don't have to change code to change which specific implementation gets injected, unless you consider your configuration code, which many do.
If you use a Factory to create configured objects that are used by the rest of your code, you are writing code to create the objects, configure them, etc. If you want to change what the factory returns, you have to change actual code, which some would argue is a more intrusive change.
Typically Spring is used to configure how the various layers of your application are wired together. X service takes such and such DAO implementations, for example. That's application level organization. Lets say you have a scenario where want to create a button for every row in a list -- in that case you could use a factory to create the buttons. This scenario is based on a runtime situation where the GUI has different elements that you couldn't configure up front (because its based on the data), so DI makes less sense here.
EDIT - based on your comment questions, I think the primary point here is that you have to consider is that Spring is also an Inversion of Control container. That means you don't program in which components in your application go where. Without IoC, you might do something like
MyServiceImpl extends MyService {
Dao1 = new Dao1Impl(); // you programmatically configure which components go in here
Dao2 = new Dao2Impl();
....
}
instead you do something like
MyServiceImpl extends MyService {
public Dao1; // you haven't specified which components, only interfaces
public Dao2;
....
}
In the second code sample, Spring (or whatever you use) will inject the appropriate DAO instances for you. You have moved control of which components to use to a higher level. So IoC and DI go hand and hand, IoC promotes loose coupling because in your component definitions (i.e. interfaces) you only specify behavior.
In other words, IoC and DI are not necessary for loose coupling; you can have loose coupling with a Factory too
MyServiceImpl extends MyService {
public dao1
public dao2;
MyServiceImpl(){
dao1 = DaoFactory.getDao1();
...
}
....
}
here your service still only depends on DAO definitions and you use the factory to get implementations. The caveat is that your service is now coupled to the factory. You can make it more loose by passing a Factory into your constructor if you want....
Also, dont forget that Spring provides other useful functionalities, like its transaction management. That's incredibly helpful, even though you said for your app you don't need it.
But could not get how spring DI loosely coupled and less intrusive
than factory classes? in both the cases we have to insert some kind of
get object code in our core program .
Spring makes it less intrusive because it uses reflection to automatically "inject/create" the dependencies. Thus your code does not need a reference to a the factory.
Spring is generally used for "Singleton-like" object creation. People generally use custom factories for transient throw away object creation (like request objects).
In fact often times you will make Spring create and inject your custom factories (ie factory of a factory).
Can an annotated Spring MVC Controller also be annotated with #Component/#Service type of annotations and be used both as a controller and as a bean?
Edit: placing more emphasis on the software design aspect, and updating the API link to SpringV3
As mentioned in other answers, this is not an ideal approach to Spring MVC, but nevertheless the controller will already be available for autowiring in your ApplicationContext.
It's already a Bean in your ApplicationContext, so you can auto-wire it by type. There's no need to add an #Component annotation.
From the Spring API Docs: "This annotation serves as a specialization of #Component, allowing for implementation classes to be autodetected through classpath scanning."
http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/stereotype/Controller.html
The same holds true for #Service.
Although I've done it myself, I would not normally recommend this design approach.
If possible, refactor the required functionality into a separate bean, which can then be (auto-)wired into both the #Controller, and any other bean, as required.
If, as you have commented, you are 'cornered' into this decision (as I was, by previous design choices), then so be it.
HTH
It can but it shouldn't. A web controller should be an entry point, nothing else.
Any reusable logic it performs should be in a dedicated service layer, not in the controller itself
No, sounds like it's doing too much. One or the other, not both. I don't know if it's possible (I doubt it), but I'm sure it's not advisable.
I think that you should hear more about patterns like Front Controller, MVC, DAO and Multitier architecture and so on.