Spring全家桶(七)通过注解配置Bean

来源:互联网 发布:linux jre6安装 编辑:程序博客网 时间:2024/05/21 14:43

Spring是简化j2ee开发的一个框架,通过指定id、类名配置bean虽然简单,但是当bean很多的时候,spring的配置文件会过于臃肿,使用注解技术配置bean使配置更加简介。

一、注解配置bean步骤

注解配置bean的原理是组件扫描,通过在spring配置文件中定义包扫描器,spring就能从classpath下自动扫描、侦测和实例化具有特定注解的bean。

Spring注解有以下四个,位于org.springframework.stereotype目录下。

  1. Component
    基本注解,标识了一个受Spring管理的组件,源码如下:

    package org.springframework.stereotype;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Component {    String value() default "";}
  2. Repository

    标识持久层组件,源码如下:

    package org.springframework.stereotype;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Repository {    String value() default "";}
  3. Service
    标识业务层组件

    package org.springframework.stereotype;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Service {    String value() default "";}
  4. Controller

    标识表现层组件

    package org.springframework.stereotype;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Controller {    String value() default "";}

配置bean的步骤:

  1. 在java类中加上Spring标准
  2. 配置文件中扫类所在的包
  3. IOC容器获取bean

Spring有一个默认的bean命名策略:使用非限定类名,第一个字母小写,或者通过value属性设置。举例,一个UserService类,通过Service注解标准了:

package com.stuspring.annbeans.service;import org.springframework.stereotype.Service;/** * Created by bee on 17/5/4. */@Servicepublic class UserService {    public void add(){        System.out.println("UserService add..");    }}

在Spring的配置文件中定义组件扫描器(注意引入context命名空间):

<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"><context:component-scan base-package="com.stuspring.annbeans" /></beans>

现在Bean已经可以使用了,它的id就是类名UserService首字母小写,即userService。获取bean并调用add方法:

package com.stuspring.annbeans;import com.stuspring.annbeans.service.UserService;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * Created by bee on 17/5/4. */public class Main {    public static void main(String[] args) {        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");        UserService userService = (UserService) ctx.getBean("userService");        System.out.println(userService);        userService.add();    }}

打印结果:

com.stuspring.annbeans.service.UserService@c81cdd1UserService add..

可以通过value属性来设置bean的id,代码如下,这样bean的id就改为uService了。

@Service("uService")public class UserService {    public void add(){        System.out.println("UserService add..");    }}

二、组件扫描器中的一些配置

<context:component-scan >可以定义一些属性及配置:

  • base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包及其子包中的所有类。需要扫描多个包时,可以使用逗号分开。
  • 如果仅需要扫描特定的类而不是基类包下的所有类,可以使用resource-pattern属性过滤特定的类。例如:

    <context:component-scan base-package="com.stuspring.annbeans" resource-pattern="repository/8.class"/>
  • <context:exclude-filter>子节点表示排除在外的目标类

  • <context:include-filter>子节点表示要包含的目标类

三、bean直接的关联关系

在UserController类中创建一个UserService对象:

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

这时候获取UserController对象:

public class Main {    public static void main(String[] args) {        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");        UserController userController = (UserController) ctx.getBean("userController");        userController.execute();    }}

运行会报空指针异常:

Exception in thread "main" java.lang.NullPointerException    at com.stuspring.annbeans.controller.UserController.execute(UserController.java:18)    at com.stuspring.annbeans.Main.main(Main.java:15)UserController execute...

从打印结果中可以看出UserService在UserController类中没有被标准。<context:component-scan>元素会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可以自动装配具有@Autowired、@Resource、@Inject注解的属性。

在UserService对象上添加注解@Autowired:

@Autowiredprivate UserService userService;

这样UserService对象就会自动装配上。

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

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