Spring4.0学习笔记006——Bean的配置(基于注解)

1. 基于注解来配置Bean

1-2. 特定注解

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

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

虽然上述的特定注解中@Respository、@Service、@Controller三个注解被建议用于表示持久层、服务层、表现层的组件,但是这仅仅只是建议而且,任何组件上应用其中的任何一个注解都可以被Spring管理到。

1-2. Bean的命名规则

对于扫描到的组件,Spring有对应的命名规则:

  • 使用非限定类名,第一个字母小写。
    举例来说就是,如果带有某个注解的组件类其类名为UserInfo,那么在Spring容器中它所对应的Bean的名称(id)即为userInfo。

  • 可以在注解中通过 value 属性值来显示标识组件所对应Bean的名称
    举例来说就是,@Component(value=”userInfo”)

1-3. xml的相应设置

当在组件类上使用特定的注解之后,还需要在Spring的配置文件中声明< context:component-scan >节点,这就要求我们先要导入context命名空间。

< context:component-scan >节点的一些属性和子节点需要说明:

  • 属性base-package:指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及其子包中的所有类。当需要扫描多个包时,可以使用逗号分隔。
  • 属性resource-pattern:用来过滤特定的类(如设resource-pattern=”subPackageName/*.class”)。
  • 子节点< context:exclude-filter >:表示要排除在外的目标类。
  • 子节点< context:include-filter >:表示要包含的目标类。
    如果想要该子节点的过滤生效,还需要设置< context:component-scan >节点的属性use-default-filters值为false。

可以同时拥有若干个< context:include-filter >和< context:exclude-filter >子节点,而这些子节点又支持多种类型的过滤表达式。常用如下的两种过滤类型:

  • annotation:过滤目标是所有标注了指定注解的类
  • assinable:过滤目标是所有继承(实现)了指定类(接口)的类

看一看基于注解配置Bean的示例程序。

  1. 创建名为 com.yfyzwr.spring.beans.annotation 的package,在其中创建名为 TestComponent.java 的java文件。

    @Component
    public class TestComponent {
    
    }
  2. 创建名为 com.yfyzwr.spring.beans.annotation.respository 的package,在其中创建名为 UserRespositoryImpl.java 的java文件。

    @Repository(value="userRespository")
    public class UserRespositoryImpl {
    
    }
  3. src目录下 创建名为 AnnotationContext.xml 的xml配置文件,为其添加context命名空间。

    xmlns:context="http://www.springframework.org/schema/context"
    
    <!-- 配置对注解的扫描范围 -->
    <context:component-scan base-package="com.yfyzwr.spring.beans.annotation"></context:component-scan>
  4. com.yfyzwr.spring.beans.annotation 包中创建包含main方法的java文件。

    public class Main {
    
        public static void main(String[] args) {
    
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("AnnotationContext.xml");
    
            TestComponent testComponent = (TestComponent)context.getBean("testComponent");
            System.out.println(testComponent);
    
            UserRespositoryImpl userRespository = (UserRespositoryImpl)context.getBean("userRespository");
            System.out.println(userRespository);
        }
    
    }
  5. 运行程序,查看输出结果。

    com.yfyzwr.spring.beans.annotation.TestComponent@957cec
    com.yfyzwr.spring.beans.annotation.respository.UserRespositoryImpl@3c944f

    从输出结果可以得知,由注解@Component、@Repository所标注的类都已经被Spring容器所检测到,并且对其实例化。

2. 基于注解来自动装配Bean的属性

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

使用@Autowired注解能够自动装配具有兼容类型的单个Bean属性,它也是最常用的。

  • 构造器、数据成员(即使是非 public)、一切具有参数的方法,它们都可以应用@Authwired 注解。

  • 默认情况下, 所有使用@Authwired注解的属性都会被设置,所以当Spring找不到匹配的Bean来装配属性时(即Spring容器中没有属性所对应的类型),会抛出异常。如果该属性允许不被设置(就是有可能找不到对应的Bean类型), 那么可以设置@Authwired注解的required属性为false值。

  • 默认情况下, 当Spring容器里存在多个类型兼容的 Bean 时,通过类型匹配来实现的自动装配将无法工作。此时可以为使用@Authwired注解的属性添加新的@Qualifier注解,并在@Qualifier注解里指定Bean的名称。Spring还允许对方法的形参标注@Qualifiter以指定注入 Bean 的名称。

    举例来说就是,使用@Authwired注解的属性是interface类型,而Spring容器中又同时存在多个实现该接口的bean类,所以自动装配该属性时就不知道该为其赋值哪个实现类型的Bean对象。

看一看基于注解来自动装配Bean属性的示例程序。

  1. 修改UserRespositoryImpl类的实现。

    @Repository(value="userRespository")
    public class UserRespositoryImpl {
    
        public void sayRespository(){
    
            System.out.println("UserRespository say ...");
        }
    }
  2. 修改TestComponent类的实现。

    @Component
    public class TestComponent {
    
        private UserRespositoryImpl respository;
    
        public void execute(){
            System.out.println("TestComponent execute ...");
            respository.sayRespository();
        }
    }
  3. 修改main 方法的实现。

    public static void main(String[] args) {
    
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("AnnotationContext.xml");
    
        TestComponent testComponent = (TestComponent)context.getBean("testComponent");
        testComponent.execute();
    }
  4. 运行程序,查看输出结果。

    java.lang.NullPointerException //抛出空指针异常,TestComponent 类的respository属性为空

  5. 再改TestComponent类的实现。

    @Component
    public class TestComponent {
    
        @Autowired(required=false)
        private UserRespositoryImpl respository;
    
    // @Autowired(required=false)
    // public void setRespository(UserRespositoryImpl respository) {
    // this.respository = respository;
    // }
    
        public void execute(){
            System.out.println("TestComponent execute ...");
            respository.sayRespository();
        }
    }
  6. 运行程序,查看输出结果。

    TestComponent execute …
    UserRespository say …

你可能感兴趣的:(spring)