组件装配:
<context:component-sacan> 元素还会自动注册 AutowiredAnnotationBeanPostProcesser 实例 , 该实例可以自动装配具有 @Autowired 和 @Resource 、 @Inject 注解的属性。
使用 @Autowired 自动装配 Bean:
@Autowired 注解自动装配具有兼容类型的单个 Bean 属性:
- 构造器 , 普通字段(即使是非 public) , 一切具有参数的方法都可以用 @Autowired 注解。
- 默认情况下 , 所有使用 @Autowired 注解的属性都需要被设置。当 Spring 找不到匹配的 bean 装配属性时 , 会抛出异常 , 若某一属性允许不被设置 , 可以设置 @Autowired 注解的 required 属性为 false。
- 默认情况下 , 当 IOC 容器里存在多个类型兼容的 bean 时 , 通过类型的自动装配将无法工作 , 此时可以在 @Qualifier 注解里提供 bean 的名称。Spring 允许对方法的入参标注 @Qualifiter 已指定注入 bean 的名称。或在需要自动装配的注解中通过 value 属性值标识组件的名称。
- @Autowired 注解也可以应用在数组类型的属性上 , 此时 Spring 将会把所有匹配的 bean 进行自动装配。
- @Autowired 注解也可以应用在集合属性上 , 此时 Spring 读取该集合的类型信息 , 然后自动装配所有与之兼容的 bean。
- @Autowired 注解用在 java.util.Map 上时 , 若该 Map 的键值为 String , 那么 Spring 将自动装配与之 Map 值类型兼容的 bean , 此时 bean 的名称作为键值。
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:context="http://www.springframework.org/schema/context"
5 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
6 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
7
8 <!-- 指定 Spring IOC 容器扫描的包 -->
9 <context:component-scan base-package="com.itdjx.spring.annotation"/>
10
11 </beans>
1 package com.itdjx.spring.annotation.controller;
2
3 import com.itdjx.spring.annotation.service.UserService;
4 import org.springframework.stereotype.Controller;
5
6 /**
7 * @author Wáng Chéng Dá
8 * @create 2017-03-03 9:28
9 */
10 @Controller
11 public class UserController {
12 private UserService userService;
13
14 public void execute() {
15 System.out.println("I am UserController's execute method...");
16 userService.add();
17 }
18 }
1 package com.itdjx.spring.annotation.service;
2
3 import com.itdjx.spring.annotation.repository.UserRepository;
4 import org.springframework.stereotype.Service;
5
6 /**
7 * @author Wáng Chéng Dá
8 * @create 2017-03-03 9:26
9 */
10 @Service
11 public class UserService {
12
13 private UserRepository userRepository;
14
15 public void add() {
16 System.out.println("I am UserService's add method...");
17 userRepository.sava();
18 }
19 }
1 package com.itdjx.spring.annotation.repository;
2
3 /**
4 * @author Wáng Chéng Dá
5 * @create 2017-03-03 9:23
6 */
7 public interface UserRepository {
8
9 void sava();
10
11 }
1 package com.itdjx.spring.annotation.repository;
2
3 import org.springframework.stereotype.Repository;
4
5 /**
6 * @author Wáng Chéng Dá
7 * @create 2017-03-03 9:24
8 */
9 @Repository("userRepository")
10 public class UserRepositoryImpl implements UserRepository {
11
12 @Override
13 public void sava() {
14 System.out.println("I am UserRepositoryImpl's sava method...");
15 }
16 }
1 package com.itdjx.spring.annotation;
2
3 import com.itdjx.spring.annotation.controller.UserController;
4 import org.springframework.context.ApplicationContext;
5 import org.springframework.context.support.ClassPathXmlApplicationContext;
6
7 /**
8 * @author Wáng Chéng Dá
9 * @create 2017-03-03 9:34
10 */
11 public class Main {
12
13 public static void main(String[] args) {
14
15 ApplicationContext cxt = new ClassPathXmlApplicationContext("beans-annotation.xml");
16 UserController userController = (UserController) cxt.getBean("userController");
17 userController.execute();
18
19 }
20 }
控制台输出:
Exception in thread "main" java.lang.NullPointerException at com.itdjx.spring.annotation.controller.UserController.execute(UserController.java:16) at com.itdjx.spring.annotation.Main.main(Main.java:17)
|
原因:IOC 容器中虽然每个 bean 节点都存在 , 但是没有引入到需要引入的 bean 节点中 , 需要将需要引入的 bean 节点引入相应的 bean 节点中。
1 package com.itdjx.spring.annotation.controller;
2
3 import com.itdjx.spring.annotation.service.UserService;
4 import org.springframework.beans.factory.annotation.Autowired;
5 import org.springframework.stereotype.Controller;
6
7 /**
8 * @author Wáng Chéng Dá
9 * @create 2017-03-03 9:28
10 */
11 @Controller
12 public class UserController {
13 @Autowired
14 private UserService userService;
15
16 public void execute() {
17 System.out.println("I am UserController's execute method...");
18 userService.add();
19 }
20 }
1 package com.itdjx.spring.annotation.service;
2
3 import com.itdjx.spring.annotation.repository.UserRepository;
4 import org.springframework.beans.factory.annotation.Autowired;
5 import org.springframework.stereotype.Service;
6
7 /**
8 * @author Wáng Chéng Dá
9 * @create 2017-03-03 9:26
10 */
11 @Service
12 public class UserService {
13
14 @Autowired
15 private UserRepository userRepository;
16
17 public void add() {
18 System.out.println("I am UserService's add method...");
19 userRepository.sava();
20 }
21 }
控制台输出:
I am UserController's execute method... I am UserService's add method... I am UserRepositoryImpl's sava method...
|
假如我们将 IOC 容器中不存在的 bean 节点引入到 bean 节点中 , 会出现什么状况呢?
1 package com.itdjx.spring.annotation;
2
3
4 /**
5 * @author Wáng Chéng Dá
6 * @create 2017-03-03 8:44
7 */
8
9 public class TestObject {
10 }
1 package com.itdjx.spring.annotation.repository;
2
3 import com.itdjx.spring.annotation.TestObject;
4 import org.springframework.beans.factory.annotation.Autowired;
5 import org.springframework.stereotype.Repository;
6
7 /**
8 * @author Wáng Chéng Dá
9 * @create 2017-03-03 9:24
10 */
11 @Repository("userRepository")
12 public class UserRepositoryImpl implements UserRepository {
13
14 @Autowired
15 private TestObject testObject;
16 @Override
17 public void sava() {
18 System.out.println("I am UserRepositoryImpl's sava method...");
19 System.out.println(testObject);
20 }
21 }
控制台输出:
警告: 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 'com.itdjx.spring.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 'com.itdjx.spring.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 com.itdjx.spring.annotation.Main.main(Main.java:15) 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 'com.itdjx.spring.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 'com.itdjx.spring.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 'com.itdjx.spring.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
|
解决方法:
1 package com.itdjx.spring.annotation.repository;
2
3 import com.itdjx.spring.annotation.TestObject;
4 import org.springframework.beans.factory.annotation.Autowired;
5 import org.springframework.stereotype.Repository;
6
7 /**
8 * @author Wáng Chéng Dá
9 * @create 2017-03-03 9:24
10 */
11 @Repository("userRepository")
12 public class UserRepositoryImpl implements UserRepository {
13
14 @Autowired(required = false)
15 private TestObject testObject;
16
17 @Override
18 public void sava() {
19 System.out.println("I am UserRepositoryImpl's sava method...");
20 System.out.println(testObject);
21 }
22 }
控制台输出:
I am UserController's execute method... I am UserService's add method... I am UserRepositoryImpl's sava method... null
|
使用 @Resource 或 @Inject 自动装配 Bean:
Spring 还支持 @Resource 和 @Inject 注解 , 这两个注解和 @Autowired 注解的功能类似。
@Resource 注解要求提供一个 bean 名称的属性 , 若该属性为空 , 则自动采用标注出的变量或方法名作为 bean 的名称。
@Inject 和 @Autowired 注解一样也是按类型匹配注入的 bean , 但没有 required 属性。
建议使用 @Autowired 注解。