When we annotate a class as #Autowired, does it HAVE to be a interface or can it be a class?
All the examples of using Spring I have seen, use an interface and then implement it on a class. The interface type is then used to call a function on the Concrete class. Can we not just simply add #Autowired to a concrete class rather than an interface.
I know of the Programme to a interface analogy in JAVA, but if u are not depending on Polymorphism, then why to write an interface?
No, you don't have to use interfaces, this is completely fine as far as Spring is concerned:
#Service
public class FooService {
#Autowired
private FooDao fooDao;
}
or you can even go for construction injection:
#Service
public class FooService {
private final FooDao fooDao;
public FooService(FooDao fooDao) {
this.fooDao = fooDao;
}
}
Often interfaces are anachronic practice repeated by every subsequent generation. Don't use them if they are not required. And they aren't required if they will always have just one implementation or if you want to mock such a class (modern mocking frameworks mock classes without any problem).
There is also nothing wrong in injecting concrete classes, like FooDao in example above. It has some technical implications wrt. proxying, but nothing that can't be comprehended.
Technically #Autowired could be used for an implementation or an interface. Spring doesn't care about it. Injecting an interface is a design strategy.
#Autowired can also be used with a class instead of interface.
But, using interfaces would be a better practice , since it reduces hard coupling between the components.
Related
Why loose coupling under java code?
i don't understand, be loose coupling when using interface
why using interface?
Service.java
interface Service{
public void method();
}
in ServiceImpl.java
#Override
ServiceImpl implements Service{
public void method(){
//To-do override
}
}
When you program to the interface you usually inject that interface in other classes, when calling methods you then call the methods on the interface and not the actual implementation. Thus, when you want to switch the implementation it is as simple as replacing your #Bean method in your Configuration class with the new implementation.
Imagine you don't do this and want to change the implementation. You would need to find all occurences in your codebase and replace it with the new implementation.
Other advantages of coding to the interface include increased testability, since you can mock your dependencies, allows for the use of JDK dynamic proxy and increased cohesion between your classes.
I want to create a DAO class named BaseDAO that should have the JPA and JDBC capabilities in Spring. I mean, I want to extend JPADAOSupport and JDBCDAOSupport classes of spring in to my BaseDAO class. I am aware that multiple inheritance is not an option in Java.
I have created two separate Base classes like BaseJPADao and BaseJdbcDao extending the respective classes. Is it possible to have a single class to extend both? Is there any design pattern solving this issue. Please advise.
Why don't you have a DaoGateway bean having injected the actual JPA DAO and the JDBC DAO beans.
This gateway can then decide which DAO to delegate a given request (to JPA or to JDBC).
You should always favour composition vs inheritance when reusing functionalities.
no it is not. if it was possible, you would still have the same result as in
one class extending JPADAOSupport and JDBCDAOSupport, which you yourself say you know is not possible because multiple inheritance is impossible.
you can write to an interface, and provide two implementations, though.
This would be easy to do with delegation if they both had interface level access you want:
public class MyUberClass implements WhateverJPADAOSupportDoes, WhateverJDBCDAOSupportDoes {
private JPADAOSuport jpa;
private JDBCDAOSupport jdbc;
// now implement all methods specified by the interfaces on the class signature and delegate to their respective member
}
But it seems you want access to all of their public methods. As there is no interface for both you can do the same as above but it can't be of both types simultaneously. The language expressly denies you this.
Your only other option is to create an adapter interface that your code can rely on and then use the combination delegation. If you're hoping to have one class that you can just drop in as a substitution for both then the answer is you can't.
I have quite good understanding of DI in general. The only issue which puzzles me is it safe to autowire inside interface? When we autowire inside interface then essentially we are not transparently introudicing tight coupling as we mandate that such and such interface should have something injected inside so its implementation should too. I also heard that it may give headache for AOP and transactional annotations. To support question with example consider:
#Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {
#PersistenceContext
private EntityManager em;
That is traditional - no problems here. Just assume I refer to #PersistenceContext as to #Autowired which is practically the same except for JPA. Now consider another example where my head explodes.
Instead of injecting entityManger inside UserRepositoryImpl, we can inject it inside UserRepository.
public interface UserRepository {
#PersistenceContext
private EntityManager em;
User save(User user);
Please explain whether there are benefits of doing this and are there any traps I have to be aware.
The motivation is: if we code to interfaces then we should do it 100%. Yet when we do it(in the second approach), we enforce dependencies for other implementations not necessarily requiring the same dependencies in their implementations , what if I want to use jdbcTemplate in my other implementation? Of course you can retaliate with ORM native querying but that's not the point.
What I have shown is not interface dependency injection. Just upfront declaration. :-)
Thanks!
I just realised I may have been wrong slightly - in interface it should be setter injection not shorthand notation, anyway the question remains the same.
The question from the title in code:
#Transactional (readonly = true)
public interface FooService {
void doSmth ();
}
public class FooServiceImpl implements FooService {
...
}
vs
public interface FooService {
void doSmth ();
}
#Transactional (readonly = true)
public class FooServiceImpl implements FooService {
...
}
From http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html
The Spring team's recommendation is that you only annotate concrete classes with the #Transactional annotation, as opposed to annotating interfaces. You certainly can place the #Transactional annotation on an interface (or an interface method), but this will only work as you would expect it to if you are using interface-based proxies. The fact that annotations are not inherited means that if you are using class-based proxies then the transaction settings will not be recognised by the class-based proxying infrastructure and the object will not be wrapped in a transactional proxy (which would be decidedly bad). So please do take the Spring team's advice and only annotate concrete classes (and the methods of concrete classes) with the #Transactional annotation.
Note: Since this mechanism is based on proxies, only 'external' method calls coming in through the proxy will be intercepted. This means that 'self-invocation', i.e. a method within the target object calling some other method of the target object, won't lead to an actual transaction at runtime even if the invoked method is marked with #Transactional!
(Emphasis added to the first sentence, other emphasis from the original.)
Spring's recommendation is that you annotate the concrete implementations instead of an interface. It's not incorrect to use the annotation on an interface, it's just possible to misuse that feature and inadvertently bypass your #Transaction declaration.
If you've marked something transactional in an interface and then refer to one of its implementing classes elsewhere in spring, it's not quite obvious that the object that spring creates will not respect the #Transactional annotation.
In practice it looks something like this:
public class MyClass implements MyInterface {
private int x;
public void doSomethingNonTx() {}
#Transactional
public void toSomethingTx() {}
}
You can put them on the interface but be warn that transactions may not end up happening in some cases. See the second tip in Secion 10.5.6 of the Spring docs:
Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the #Transactional annotation, as opposed to annotating interfaces. You certainly can place the #Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies. The fact that Java annotations are not inherited from interfaces means that if you are using class-based proxies (proxy-target-class="true") or the weaving-based aspect (mode="aspectj"), then the transaction settings are not recognized by the proxying and weaving infrastructure, and the object will not be wrapped in a transactional proxy, which would be decidedly bad.
I would recommend putting them on the implementation for this reason.
Also, to me, transactions seem like an implementation detail so they should be in the implementation class. Imagine having wrapper implementations for logging or test implementations (mocks) that don't need to be transactional.
Supporting #Transactional on the concrete classes:
I prefer to architect a solution in 3 sections generally: an API, an Implementation and a Web (if needed). I try my best to keep the API as light/simple/POJO as possible by minimizing dependencies. It's especially important if you play it in a distributed/integrated environment where you have to share the APIs a lot.
Putting #Transactional requires Spring libraries in the API section, which IMHO is not effective. So I prefer to add it in the Implementation where the transaction is running.
Putting it on the interface is fine as long all foreseeable implementers of your IFC care about TX data (transactions aren't problems that just databases deal with). If the method doesn't care about TX (but you need to put it there for Hibernate or whatever), put it on the impl.
Also, it might be a bit better to place #Transactional on the methods in the interface:
public interface FooService {
#Transactional(readOnly = true)
void doSmth();
}
I have a strange behaviour when autowiring
I have a similar code like this one, and it works
#Controller
public class Class1 {
#Autowired
private Class2 object2;
...
}
#Service
#Transactional
public class Class2{
...
}
The problem is that I need that the Class2 implements an interface so I've only changed the Class2 so it's now like:
#Controller
public class Class1 {
#Autowired
private Class2 object2;
...
}
#Service
#Transactional
public class Class2 implements IServiceReference<Class3, Long>{
...
}
public interface IServiceReference<T, PK extends Serializable> {
public T reference(PK id);
}
with this code I get a org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type for Class2.
It seems that #Transitional annotation is not compatible with the interface because if I remove the #Transitional annotation or the implements IServiceReference<Class3, Long> the problem disapears and the bean is injected (though I need to have both in this class). It also happens if I put the annotation #Transitional in the methods instead of in the Class.
I use Spring 3.0.2 if this helps.
Is not compatible the interface with the transactional method?
May it be a Spring bug?
The problem is that your Class1 needs a reference to IServiceReference and not the concrete reference of Class2
#Controller
public class Class1 {
#Autowired
private IServiceReference object2;
...
}
The reason this is that Spring is creating a dynamic proxy for classes that you marked #Transactional. Thus when Class2 is created its wrapped in a Proxy object that is obviously not of type Class2 but is of type IServiceReference.
If you want the behavior of using Class2 with proxy support you will have to turn on CGLIB
Read below:
From Springs Doc:
Spring AOP defaults to using standard
J2SE dynamic proxies for AOP proxies.
This enables any interface (or set of
interfaces) to be proxied.
Spring AOP can also use CGLIB proxies.
This is necessary to proxy classes,
rather than interfaces. CGLIB is used
by default if a business object does
not implement an interface. As it is
good practice to program to interfaces
rather than classes, business classes
normally will implement one or more
business interfaces. It is possible to
force the use of CGLIB, in those
(hopefully rare) cases where you need
to advise a method that is not
declared on an interface, or where you
need to pass a proxied object to a
method as a concrete type.
It is important to grasp the fact that
Spring AOP is proxy-based. See the
section entitled Section 6.6.1,
“Understanding AOP proxies” for a
thorough examination of exactly what
this implementation detail actually
means.
The Transactional annotation instructs Spring to generate proxy objects around the annotated beans, to implement the transactional semantics. The generated proxy will implement the same interfaces as the target bean. So if your target bean implements IServiceReference, then so will the generated proxy.
If the target bean has no implemented interfaces, then the generated proxy will instead be a subclass of the target bean type.
In your original example, the transactional proxy will be a subclass of Class2, because Class2 implemented no interfaces. When you changed Class2 to implement IServiceReference, the generated proxy no longer extended Class2, and instead implemented IServiceReference. This caused your ClassCastException.
The best approach to this situation is to remove the reference from Class1 to Class2, and instead talk to Class2 purely through its interfaces. Class2 can implement as many interfaces as you like, the proxy will implement all of them.
You can force Spring to generate subclass proxies regardless of the interfaces, but it's additional complexity, and I'd recommend against it.
You can force it to proxy by adding
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
also see this documentation.