Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
200 views
in Technique[技术] by (71.8m points)

java - @Autowire strange problem

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...