Spring入门第十六课

接上一次讲课

先看代码:

package logan.spring.study.annotation.repository;

public interface UserRepository {

    void save();

}
package logan.spring.study.annotation.repository;

import org.springframework.stereotype.Repository;

@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {

    @Override
    public void save() {
        // TODO Auto-generated method stub
        System.out.println("UserRepository Save...");

    }

}
package logan.spring.study.annotation.service;

import org.springframework.stereotype.Service;

import logan.spring.study.annotation.repository.UserRepository;

@Service
public class UserService {

    private UserRepository userRepository;

    public void add(){
        System.out.println("UserService add...");
        userRepository.save();
    }
}
package logan.spring.study.annotation.controller;

import org.springframework.stereotype.Controller;

import logan.spring.study.annotation.service.UserService;

@Controller
public class UserController {

    UserService userService;
    public void execute(){
        System.out.println("UserController execute...");
        userService.add();
    }

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    <context:component-scan
    base-package="logan.spring.study.annotation">
    </context:component-scan>

</beans>
package logan.spring.study.annotation;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import logan.spring.study.annotation.controller.UserController;
import logan.spring.study.annotation.repository.UserRepository;
import logan.spring.study.annotation.service.UserService;

public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");
//        TestObject to = (TestObject) ctx.getBean("testObject");
//        System.out.println(to);

        UserController userController = (UserController) ctx.getBean("userController");
        System.out.println(userController);
        userController.execute();

//        UserService userService = (UserService) ctx.getBean("userService");
//        System.out.println(userService);

//        UserRepository userRepository = (UserRepository) ctx.getBean("userRepository");
//        System.out.println(userRepository);
    }
}

输出结果:

五月 27, 2017 11:15:37 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org[email protected]42110406: startup date [Sat May 27 11:15:37 CST 2017]; root of context hierarchy
五月 27, 2017 11:15:37 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans-annotation.xml]
Exception in thread "main" [email protected]
UserController execute...
java.lang.NullPointerException
    at logan.spring.study.annotation.controller.UserController.execute(UserController.java:13)
    at logan.spring.study.annotation.Main.main(Main.java:18)

可以看到空指针异常,因为没有办法调用userController.execute();

组件装配

<context:component-scan>元素还会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可以自动装配具有@Autowired和@Resource,@Inject注解的属性。

使用@Autowired自动装配Bean

@Autowired注解自动装配具有兼容类型的单个Bean属性:

-构造器,普通字段(即使是非public),一切具有参数的方法都可以应用@Autowired注解

-默认情况下,所有使用@Autowired注解的属性都要被设置,当Spring找不到匹配度Bean装配属性时,会抛出异常,若某一属性允许不被设置,可以设置@Autowired注解的required属性为false.

-默认情况下,当IOC容器里存在多个类型兼容的Bean时,通过类型的自动装配将无法工作,此时可以在@Qualifiter注解里面提供Bean的名称,Spring允许对方法的入参标注@Qualifiter已指定注入Bean的名称。

[email protected]注解也可以应用在数组类型的属性上,此时Spring将会把所有匹配的Bean警醒自动装配。

[email protected]注解也可以应用在集合属性上,此时Spring读取该集合的类型信息,然后自动装配所有与之兼容的Bean。

[email protected]注解用在java.util.map上时,若该Map的键值为String,那么Spring将自动装配与之Map值类型兼容的Bean,此时Bean的名称作为键值。

看如下代码:

package logan.spring.study.annotation.repository;

public interface UserRepository {

    void save();

}
package logan.spring.study.annotation.repository;

import org.springframework.stereotype.Repository;

@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {

    @Override
    public void save() {
        // TODO Auto-generated method stub
        System.out.println("UserRepository Save...");

    }

}
package logan.spring.study.annotation.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import logan.spring.study.annotation.repository.UserRepository;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public void add(){
        System.out.println("UserService add...");
        userRepository.save();
    }
}
package logan.spring.study.annotation.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import logan.spring.study.annotation.service.UserService;

@Controller
public class UserController {
    @Autowired
    UserService userService;
    public void execute(){
        System.out.println("UserController execute...");
        userService.add();
    }

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    <context:component-scan
    base-package="logan.spring.study.annotation">
    </context:component-scan>

</beans>
package logan.spring.study.annotation;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import logan.spring.study.annotation.controller.UserController;
import logan.spring.study.annotation.repository.UserRepository;
import logan.spring.study.annotation.service.UserService;

public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");
//        TestObject to = (TestObject) ctx.getBean("testObject");
//        System.out.println(to);

        UserController userController = (UserController) ctx.getBean("userController");
        System.out.println(userController);
        userController.execute();

//        UserService userService = (UserService) ctx.getBean("userService");
//        System.out.println(userService);

//        UserRepository userRepository = (UserRepository) ctx.getBean("userRepository");
//        System.out.println(userRepository);
    }
}

输出结果:

五月 27, 2017 12:16:53 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org[email protected]42110406: startup date [Sat May 27 12:16:53 CST 2017]; root of context hierarchy
五月 27, 2017 12:16:53 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans-annotation.xml]
[email protected]
UserController execute...
UserService add...
UserRepository Save...

在看如下代码:

package logan.spring.study.annotation;

import org.springframework.stereotype.Component;

@Component
public class TestObject {

}
package logan.spring.study.annotation.repository;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import logan.spring.study.annotation.TestObject;

@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {
    @Autowired
    private TestObject testObject;

    @Override
    public void save() {
        // TODO Auto-generated method stub
        System.out.println("UserRepository Save...");
        System.out.println(testObject);

    }

}
package logan.spring.study.annotation;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import logan.spring.study.annotation.controller.UserController;
import logan.spring.study.annotation.repository.UserRepository;
import logan.spring.study.annotation.service.UserService;

public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");
//        TestObject to = (TestObject) ctx.getBean("testObject");
//        System.out.println(to);

        UserController userController = (UserController) ctx.getBean("userController");
        System.out.println(userController);
        userController.execute();

//        UserService userService = (UserService) ctx.getBean("userService");
//        System.out.println(userService);

//        UserRepository userRepository = (UserRepository) ctx.getBean("userRepository");
//        System.out.println(userRepository);
    }
}

输出结果为:

五月 27, 2017 1:22:00 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org[email protected]42110406: startup date [Sat May 27 13:21:59 CST 2017]; root of context hierarchy
五月 27, 2017 1:22:00 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans-annotation.xml]
[email protected]
UserController execute...
UserService add...
UserRepository Save...
[email protected]

如果没有TestObject就会出错,如下:

package logan.spring.study.annotation;

public class TestObject {

}

输出结果为:

五月 27, 2017 1:25:00 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org[email protected]42110406: startup date [Sat May 27 13:25:00 CST 2017]; root of context hierarchy
五月 27, 2017 1:25:00 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans-annotation.xml]
五月 27, 2017 1:25:00 下午 org.springframework.context.support.ClassPathXmlApplicationContext refresh
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userController‘: Unsatisfied dependency expressed through field ‘userService‘; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userService‘: Unsatisfied dependency expressed through field ‘userRepository‘; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userRepository‘: Unsatisfied dependency expressed through field ‘testObject‘; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ‘logan.spring.study.annotation.TestObject‘ available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userController‘: Unsatisfied dependency expressed through field ‘userService‘; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userService‘: Unsatisfied dependency expressed through field ‘userRepository‘; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userRepository‘: Unsatisfied dependency expressed through field ‘testObject‘; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ‘logan.spring.study.annotation.TestObject‘ available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at logan.spring.study.annotation.Main.main(Main.java:12)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userService‘: Unsatisfied dependency expressed through field ‘userRepository‘; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userRepository‘: Unsatisfied dependency expressed through field ‘testObject‘; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ‘logan.spring.study.annotation.TestObject‘ available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    ... 15 more
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userRepository‘: Unsatisfied dependency expressed through field ‘testObject‘; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ‘logan.spring.study.annotation.TestObject‘ available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    ... 28 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ‘logan.spring.study.annotation.TestObject‘ available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1486)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    ... 41 more

如果没有TestObject,还想让编译成功,如下:

package logan.spring.study.annotation.repository;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import logan.spring.study.annotation.TestObject;

@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {
    @Autowired(required=false)
    private TestObject testObject;

    @Override
    public void save() {
        // TODO Auto-generated method stub
        System.out.println("UserRepository Save...");
        System.out.println(testObject);

    }

}

输出结果为:

五月 27, 2017 1:29:07 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org[email protected]42110406: startup date [Sat May 27 13:29:07 CST 2017]; root of context hierarchy
五月 27, 2017 1:29:07 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans-annotation.xml]
[email protected]
UserController execute...
UserService add...
UserRepository Save...
null

如果有好几个类型相同的Bean,会出错吗?

看如下代码:

package logan.spring.study.annotation.repository;

import org.springframework.stereotype.Repository;

@Repository
public class UserJdbcRepository implements UserRepository{

    @Override
    public void save() {
        // TODO Auto-generated method stub
        System.out.println("UserJdbcRepository save....");

    }

}
package logan.spring.study.annotation.repository;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import logan.spring.study.annotation.TestObject;

@Repository
public class UserRepositoryImpl implements UserRepository {
    @Autowired(required=false)
    private TestObject testObject;

    @Override
    public void save() {
        // TODO Auto-generated method stub
        System.out.println("UserRepository Save...");
        System.out.println(testObject);

    }

}

这样会运行出错:

五月 27, 2017 1:33:57 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org[email protected]42110406: startup date [Sat May 27 13:33:57 CST 2017]; root of context hierarchy
五月 27, 2017 1:33:57 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans-annotation.xml]
五月 27, 2017 1:33:58 下午 org.springframework.context.support.ClassPathXmlApplicationContext refresh
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userController‘: Unsatisfied dependency expressed through field ‘userService‘; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userService‘: Unsatisfied dependency expressed through field ‘userRepository‘; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘logan.spring.study.annotation.repository.UserRepository‘ available: expected single matching bean but found 2: userJdbcRepository,userRepositoryImpl
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userController‘: Unsatisfied dependency expressed through field ‘userService‘; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userService‘: Unsatisfied dependency expressed through field ‘userRepository‘; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘logan.spring.study.annotation.repository.UserRepository‘ available: expected single matching bean but found 2: userJdbcRepository,userRepositoryImpl
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at logan.spring.study.annotation.Main.main(Main.java:12)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userService‘: Unsatisfied dependency expressed through field ‘userRepository‘; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘logan.spring.study.annotation.repository.UserRepository‘ available: expected single matching bean but found 2: userJdbcRepository,userRepositoryImpl
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    ... 15 more
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘logan.spring.study.annotation.repository.UserRepository‘ available: expected single matching bean but found 2: userJdbcRepository,userRepositoryImpl
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:173)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    ... 28 more

解决方法就是指定userRepository

package logan.spring.study.annotation.repository;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import logan.spring.study.annotation.TestObject;

@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {
    @Autowired(required=false)
    private TestObject testObject;

    @Override
    public void save() {
        // TODO Auto-generated method stub
        System.out.println("UserRepository Save...");
        System.out.println(testObject);

    }

}

输出结果为:

五月 27, 2017 1:37:26 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org[email protected]42110406: startup date [Sat May 27 13:37:26 CST 2017]; root of context hierarchy
五月 27, 2017 1:37:26 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans-annotation.xml]
[email protected]
UserController execute...
UserService add...
UserRepository Save...
null

还可以在UserService里面指定:

package logan.spring.study.annotation.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import logan.spring.study.annotation.repository.UserRepository;

@Service
public class UserService {

    @Autowired
    @Qualifier("userRepositoryImpl")
    private UserRepository userRepository;

    public void add(){
        System.out.println("UserService add...");
        userRepository.save();
    }
}
package logan.spring.study.annotation.repository;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import logan.spring.study.annotation.TestObject;

@Repository
public class UserRepositoryImpl implements UserRepository {
    @Autowired(required=false)
    private TestObject testObject;

    @Override
    public void save() {
        // TODO Auto-generated method stub
        System.out.println("UserRepository Save...");
        System.out.println(testObject);

    }

}

输出结果为:

五月 27, 2017 1:41:07 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org[email protected]42110406: startup date [Sat May 27 13:41:07 CST 2017]; root of context hierarchy
五月 27, 2017 1:41:07 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans-annotation.xml]
[email protected]
UserController execute...
UserService add...
UserRepository Save...
null

对于set方法也是可以的,如下看代码:

package logan.spring.study.annotation.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import logan.spring.study.annotation.repository.UserRepository;

@Service
public class UserService {

    private UserRepository userRepository;

    @Autowired
    @Qualifier("userRepositoryImpl")
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void add(){
        System.out.println("UserService add...");
        userRepository.save();
    }
}

输出结果为:

五月 27, 2017 1:42:58 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org[email protected]42110406: startup date [Sat May 27 13:42:58 CST 2017]; root of context hierarchy
五月 27, 2017 1:42:58 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans-annotation.xml]
[email protected]
UserController execute...
UserService add...
UserRepository Save...
null

还可以放在入参的里面:

package logan.spring.study.annotation.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import logan.spring.study.annotation.repository.UserRepository;

@Service
public class UserService {

    private UserRepository userRepository;

    @Autowired
    public void setUserRepository(@Qualifier("userRepositoryImpl") UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void add(){
        System.out.println("UserService add...");
        userRepository.save();
    }
}
时间: 2024-08-28 23:18:36

Spring入门第十六课的相关文章

Spring入门第十九课

后置通知 看代码: package logan.study.aop.impl; public interface ArithmeticCalculator { int add(int i, int j); int sub(int i, int j); int mul(int i, int j); int div(int i, int j); } package logan.study.aop.impl; import org.springframework.stereotype.Componen

Spring入门第十八课

Spring AOP AspectJ:Java社区里最完整最流行的AOP框架 在Spring2.0以上的版本中,可以使用基于AspectJ注解或者基于XML配置的AOP 看代码: package logan.study.aop.impl; public interface ArithmeticCalculator { int add(int i, int j); int sub(int i, int j); int mul(int i, int j); int div(int i, int j)

Spring入门第十四课

基于注解的方式配置bean(基于注解配置Bean,基于注解来装配Bean的属性) 在classpath中扫描组件 组件扫描(component scanning):Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件. 特定组件包括: [email protected]:基本注解,表示了一个受Spring管理的组件 [email protected]:标识持久层组件 [email protected]:标识服务层组(业务层)件 [email protected]:标识表

Spring入门第十二课

Bean的配置方法 通过工厂方法(静态工厂方法&实例工厂方法),FactoryBean 通过调用静态工厂方法创建Bean 调用静态工厂方法创建Bean是将对象创建的过程封装到静态方法中,当客户端需要对象时,只需要简单的调用静态方法,而不用关心创建对象的细节. 要声明通过静态方法创建的Bean,需要在Bean的class属性里指定拥有该工厂的方法类,同时在factory-method属性里指定工厂方法的名称,最后,使用<constructor-arg>元素为该方法传递方法参数. 看代码

Spring入门第十课

Spring表达式语言:SpEL Spring表达式语言(简称SpEL)是一个支持运行时查询和操作对象图的强大的表达式语言. 语法类似于EL:SpEL使用#{...}作为定界符,所有在大括号中的字符都将被认为是SpEL SpEL为bean的属性进行动态复制提供了便利. 通过SpEL可以实现: -通过bean的id对bean进行引用 -调用方法以及引用对象中的属性 -计算表达式的值 -正则表达式的匹配 下面看如何使用 package logan.spring.study.spel; public

Spring入门第二十六课

Spring中的事务管理 事务简介 事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性. 事务就是一系列的动作,他们被当做一个单独的工作单元,这些动作要么全部完成,要么全部不起作用. 事务的四个关键属性(ACID) -原子性(atomicity):事务是一个原子操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用. -一致性(consistency):一旦所有事务动作完成,事务就被提交,数据和资源就处于一种满足业务规则的一致性状态中. -隔离性(is

第十六课 数组的引入 【项目1-5】

第十六课 数组的引入 项目一 [数组大折腾] (1)创建一个有20个元素的整型数组,通过初始化,为数组中的前10个元素赋初值,然后通过键盘输入后10个元素的值,从前往后(从第0个到第19个)输出数组中元素的值,每5个元素换一行. [cpp] view plain copy print? int main( ) { int a[20]={...};  //初始化前10个元素 //键盘输入后10个元素的值 //由前往后输出数组中所有元素的值 printf("由前往后,数组中的值是:\n")

第十六课----Rsync数据同步工具

1.1.1 什么是Rsync?Rsync是一款开源的,快速的,多功能的,可实现全量及增量的本地或远程数据同步备份的优秀工具.Rsync软件适用于unix/linux/windows等多种操作系统平台.1.1.2 Rsync简介? Rsync英文全称Remote synchronization,从软件的名称就可以看出来,Rsync具有可使本地和远程两台主机之间的数据快速复制同步镜像,远程备份的功能,这个功能类似ssh带的scp命令,但又优于scp命令的功能,scp每次都是全量拷贝,而rsync可以

Python第十六课(模块3)

Python第十六课(模块3)    >>>思维导图>>>中二青年 模块与包 模块 """ 三种来源 1.内置的 2.第三方的 3.自定义的 四种表示形式 1.py文件(******) 2.共享库 3.文件夹(一系列模块的结合体)(******) 4.C++编译的连接到python内置的 """ 导入模块 """ 先产生一个执行文件的名称空间 1.创建模块文件的名称空间 2.执行模