image.png

在classpath中扫描组件

  • 组件扫描(component scanning):Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件
  • 特定组件包括

  • @Component : 基本注解,标识了一个受Spring管理的组件
    - @Respository:标识持久层组件
    - @Service:标识服务层(业务层)组件
    - @Controller :标识表现层(视图层)组件

  • 对于扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写,也可以在注解中通过value属性值标识组件的名称

  • 当在组件类上使用了特定的注解之后,还需要在Spring的配置文件中声明:

-base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及其子包中的所有类。
-当需要扫描多个包时,可以使用逗号分隔。
-如果仅希望扫描特定的类而非基类包下的所有类,可以使用resource-pattern属性过滤特定的类,示例在下面

  • 子节点支持多种类型的过滤表达式

-type=”annotation” 过滤目标类
-type=”assinable” 所有继承或扩展目标类的类
-aspectj 所有类名以“某个名称”结束以及继承或扩展它们的类
-regex 正则匹配
-custom 采用Filter通过代码的方式定义过滤规则,该类必须实现org.springframework.core.type.TypeFilter接口

  1. <context:component-scan
  2. base-package="com.lijunyang"
  3. resource-pattern="autowire/*class">
  4. <!--
  5. <context:include-filter>子节点表示要包含的目标类
  6. <context:exclude-filter>子节点表示要排除在外的目标类
  7. <context:component-scan>下可以拥有若干个<context:include-filter>
  8. <context:exclude-filter>子节点
  9. -->
  10. </context:component-scan>
  11. <context:component-scan
  12. base-package="com.lijunyang"
  13. use-default-filters="false">
  14. <!-- <context:include-filter>节点要配合use-default-filters使用 -->
  15. <context:include-filter type="annotation"
  16. expression="org.springframework.stereotype.Repository" />
  17. </context:component-scan>
  18. <context:component-scan
  19. base-package="com.lijunyang">
  20. <context:exclude-filter type="annotation"
  21. expression="org.springframework.stereotype.Repository" />
  22. </context:component-scan>
  1. /*
  2. spring-demo
  3. |- /src
  4. |- beans.xml
  5. |- com
  6. |- lijunyang
  7. |- test
  8. |- Main.java
  9. |- model
  10. |- TestObject.java
  11. |- service
  12. |- UserService.java
  13. |- repository
  14. |- UserRepository.java
  15. |- UserRepositoryImpl.java
  16. |- controller
  17. |- UserComtroller.java
  18. */
  19. // TestObject.java
  20. import org.springframework.stereotype.Component
  21. @Conponent
  22. public class TestObject {
  23. }
  24. // UserRepository.java
  25. public interface UserRepository {
  26. void save();
  27. }
  28. // UserRepositoryImpl.java
  29. import org.springframework.stereotype.Repository
  30. @Repository("userRepository")
  31. public class UserRepositoryImpl implements UserRepository {
  32. @Override
  33. public void save() {
  34. System.out.println("UserRepository Save...");
  35. }
  36. }
  37. // UserService.java
  38. import org.springframework.stereotype.Service
  39. @Service
  40. public class UserService {
  41. public void add() {
  42. System.out.println("UserService Add...");
  43. }
  44. }
  45. // UserComtroller.java
  46. import org.springframework.stereotype.Controller
  47. public class UserController {
  48. public void execute() {
  49. System.out.println("UserController execute...");
  50. }
  51. }
  52. // Main.java
  53. public class Main {
  54. public static main(String args[]) {
  55. ApplicationContext ct = new ClassPathXmlApplicationContext("beans.xml");
  56. TestObject to = (TestObject) ct.getBean("testObject");
  57. System.out.println(to);
  58. UserController userController = (UserController) ct.getBean("userController");
  59. System.out.println(userController);
  60. UserService userService = (UserService) ct.getBean("userService");
  61. System.out.println(userService);
  62. // 当在<context:component-scan里使用了resource-pattern="repository/*class"时
  63. // 下面的bean就不在生效了,此时会抛出异常
  64. UserRepository userRepository = (UserRepository) ct.getBean("userRepository");
  65. System.out.println(userRepository);
  66. }
  67. }
  1. // beans.xml
  2. <beans>
  3. <context:component-scan
  4. base-package="com.lijunyang"
  5. resource-pattern="repository/*class"
  6. />
  7. </beans>

第二阶段的代码 与 组件装配

  • 元素还会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可以自动装配具有@Autowired和@Resource,@inject注解的属性
  • @Autowired 注解自动装配具有兼容类型的单个Bean属性

-构造器,普通字段(即使是非public),一切具有参数的方法都可以应用@Autowired注解
-默认情况下,所有使用@Autowired注解的属性都需要被设置。当Spring找不到匹配的Bean装配属性时会抛出异常,若某一个属性不被设置,可以设置@Autowired注解的required属性为false。
-默认情况下,当IOC容器里存在多个类型兼容的Bean时,通过类型的自动装配将无法工资,此时可以在@Qualifier注解里提供Bean的名称,Spring允许对方法的入参标注@Qualifier已指定注入Bean的名称
-@Autowired 注解也可以应用在数组类型的属性上,此时Spring将会把所有匹配的Bean进行自动装配
-@Autowired 注解也可以应用在集合属性上,此时Spring读取该集合的类型信息,然后自动装配所有与之兼容的Bean
-@Autowired 注解用在java.util.Map上时,若该Map的键值为String,那么Spring将自动装配与之Map值类型兼容的Bean,此时Bean的名称作为键值

  1. /*
  2. spring-demo
  3. |- /src
  4. |- beans.xml
  5. |- com
  6. |- lijunyang
  7. |- test
  8. |- Main.java
  9. |- model
  10. |- TestObject.java
  11. |- service
  12. |- UserService.java
  13. |- repository
  14. |- UserRepository.java
  15. |- UserRepositoryImpl.java
  16. |- UserJdbcRepository.java
  17. |- controller
  18. |- UserComtroller.java
  19. */
  20. // TestObject.java
  21. import org.springframework.stereotype.Component
  22. @Conponent
  23. public class TestObject {
  24. }
  25. // UserRepository.java
  26. public interface UserRepository {
  27. void save();
  28. }
  29. // UserJdbcRepository.java
  30. import org.springframework.stereotype.Repository
  31. @Repository
  32. public class UserJdbcRepository implements UserRepository {
  33. @Override
  34. public void save() {
  35. System.out.println("UserJdbcRepository Save...");
  36. }
  37. }
  38. // UserRepositoryImpl.java
  39. import org.springframework.stereotype.Repository
  40. // @Repository("userRepository")
  41. @Repository
  42. public class UserRepositoryImpl implements UserRepository {
  43. @Autowired(required=false)
  44. private TestObject testObject;
  45. @Override
  46. public void save() {
  47. System.out.println("UserRepository Save...");
  48. Syetem.out.println(testObject);
  49. }
  50. }
  51. // UserService.java
  52. import org.springframework.stereotype.Service
  53. @Service
  54. public class UserService {
  55. /*
  56. @Autowired
  57. @Qualifier("userRepositoryImpl")
  58. private UserRepository userRepository;
  59. */
  60. private UserRepository userRepository;
  61. /*
  62. @Autowired
  63. @Qualifier("userRepositoryImpl")
  64. public void setUserRepository(UserRepository userRepository) {
  65. this.userRepository = userRepository;
  66. }
  67. */
  68. @Autowired
  69. public void setUserRepository(@Qualifier("userRepositoryImpl") UserRepository userRepository) {
  70. this.userRepository = userRepository;
  71. }
  72. public void add() {
  73. System.out.println("UserService Add...");
  74. userRepository.save();
  75. }
  76. }
  77. // UserComtroller.java
  78. import org.springframework.stereotype.Controller
  79. public class UserController {
  80. @Autowired
  81. private UserService userService;
  82. public void execute() {
  83. System.out.println("UserController execute...");
  84. userService.add();
  85. }
  86. }
  87. // Main.java
  88. public class Main {
  89. public static main(String args[]) {
  90. ApplicationContext ct = new ClassPathXmlApplicationContext("beans.xml");
  91. // TestObject to = (TestObject) ct.getBean("testObject");
  92. // System.out.println(to);
  93. UserController userController = (UserController) ct.getBean("userController");
  94. System.out.println(userController);
  95. userController.execute();
  96. // UserService userService = (UserService) ct.getBean("userService");
  97. // System.out.println(userService);
  98. // 当在<context:component-scan里使用了resource-pattern="repository/*class"时
  99. // 下面的bean就不在生效了,此时会抛出异常
  100. // UserRepository userRepository = (UserRepository) ct.getBean("userRepository");
  101. // System.out.println(userRepository);
  102. }
  103. }

使用@Resource 或 @Inject 自动装配Bean

  • Spring还支持@Resource或@Inject注解,这两个注解和@Autowired注解的功能类似
  • @Resource注解要求提供一个Bean名称的属性,若该属性为null,则自动采用标注处的变量或方法名作为Bean的名称
  • @Inject和@Autowired注解一样是按类型匹配注入的Bean,但是没有reqired属性
  • 建议使用@Autowired注解