说明:
1、本实例用的是注解方式,spring配置已省略
2、使用aop管理事务
<aop:pointcut expression="execution (* com.test.service.impl.*.*(..))" id="services"/>
直接看例子:
一、 A.java
package com.test
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class A {
@Autowired
private BImpl bImpl;//注入的是接口的实现类
public void save(){
bImpl.save();
}
}
二、B.java
package com.test
public interface B {
public void save();
}
三、BImpl.java ,B接口的实现类
package com.test
import org.springframework.stereotype.Service;
@Service
public class BImpl implements B {
@Override
public void save() {
System.out.println("BImpl.save()");
}
}
异常: 服务启动会报以下错误:
No matching bean of type [BImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
可见bean装配时出现异常
源码分析:
DefaultListableBeanFactory.java
//@param type 类A中的引用BImpl的类型
private String[] doGetBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
//所有已定义的bean,此例中beanName为bImpl
String[] beanDefinitionNames = getBeanDefinitionNames();
for (String beanName : beanDefinitionNames) {
........
//@param beanName
//@param type--com.test.BImpl
boolean matchFound = isTypeMatch(beanName, type);//转AbstractBeanFactory.isTypeMatch()
........
}
}
AbstractBeanFactory.java
public boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException {
String beanName = transformedBeanName(name);
Class<?> typeToMatch = (targetType != null ? targetType : Object.class);
Object beanInstance = getSingleton(beanName, false);
......
return ClassUtils.isAssignableValue(typeToMatch, beanInstance);//转ClassUtils.isAssignable()
......
}
ClassUtils.java
class ClassUtils {
......
//lhsType -- com.test.BImpl
//rhsType -- 从spring容器中取出Bean
public static boolean isAssignable(Class<?> lhsType, Class<?> rhsType) {
//lhsType是否等于或是rhsType表示类的或接口的父类
if (lhsType.isAssignableFrom(rhsType)) {
return true;
}
......
return false;
}
......
}
结论:
1、此例中如果注入的类型为接口B
lhsType.isAssignableFrom(rhsType)返回为true,启动成功
2、此例中如果注入的类型为BImpl
A、BImpl实现了接口B,则rhsType为JDK动态代理对象,lhsType.isAssignableFrom(rhsType)返回false,启动失败
B、BImpl不实现接口B,则rhsType为CGLIB代理对象(继承目标类),lhsType.isAssignableFrom(rhsType)返回true,启动成功