这是service接口public interface AccountService {
    public List<Account> findAll();
}这是service接口的实现类@Service("accountService")
public class AccountServiceImpl implements AccountService {
    @Autowired
    AccountDao accountDao;
    @Override
    public List<Account> findAll() {
        System.out.println("业务层,查询所有账户信息");
        return accountDao.findAll();
    }
}
这是controller方法@Controller
@RequestMapping("/account")
public class AccountController {
    @Autowired
    private AccountServiceImpl accountService1;
    @RequestMapping("/findAll")
    public String findAll(){
        System.out.println("表现层--AccountController.findAll()");        List<Account> list = accountService1.findAll();
        for(Account a:list){
            System.out.println(a);
        }
        return "success";
    }
}在spring中对service的实现类(AccountServiceImpl)进行声明式事务控制,报错,报错核心信息是
Bean named 'accountService' is expected to be of type 'com.service.impl.AccountServiceImpl' but was actually of type 'com.sun.proxy.$Proxy24'
找到原因是spring的事务控制是对AccountServiceImpl进行基于接口的动态代理,将controller中的自动注入类型改为@Autowired
 private AccountService accountService1;即可。那么我就很奇怪,动态代理的原对象肯定也是存在的,为什么自动注入原对象类型会报错呢?
而且报错的信息除了注入失败以外,最主要的还是spring容器中id为accountService的bean类型本应该为AccountServiceImpl类型。spring是怎么知道bean对象原本类型的?

解决方案 »

  1.   

    @Autowired会自动进行类型匹配,但是你指定了bean的名称,需要再加上@Qualifier注解并指定名称就行了,或者直接加一个@Resources注解指定名称就行了,至于为什么找不到,仔细去看一下@Autowired是怎么进行匹配的就知道了
      

  2.   

    你controller层的注入不应该是这么写么
    @Autowired
        private AccountService accountService
      

  3.   

    Spring 动态代理默认使用的是jdk动态代理
    JDK动态代理的原理是根据定义好的规则,用传入的接口创建一个新类,所以只能用接口引用指向代理,而不能用传入的类引用执行动态类。
    例如是这个格式:
    public class $Proxy1 extends Proxy implements 传入的接口{} 
     
    如果想直接注入实现类的话,可以配置 <aop:aspectj-autoproxy proxy-target-class="true"/> 使用cglib代理;
    cglib采用的是用创建一个继承实现类的子类