Spring 注解

【Spring】Spring 深入理解注解及spring对注解的增强 1.概述 深入理解注解及spring对注解的增强 2. 什么是注解? 代码中注释大家都熟悉吧,注释是给开发者看的,可以提升代码的可读性和可维护性,但是对于java编译器和虚拟机来说是没有意义的,编译之后的字节码文件中是没有注释信息的;而注解和注释有点类似,唯一的区别就是注释是给人看的,而注解是给编译器和虚拟机看的,编译器和虚拟机在运行的过程中可以获取注解信息,然后可以根据这些注解的信息做各种想做的事情。比如:大家对@Override应该比较熟悉,就是一个注解,加在方法上,标注当前方法重写了父类的方法,当编. 阅读详情

使用Spring2.5的Autowired实现注释型的IOC   161641

   

 使用Spring2.5的新特性——Autowired可以实现快速的自动注入,而无需在xml文档里面添加bean的声明,大大减少了xml文档的维护。(偶喜欢这个功能,因为偶对xml不感冒)。       以下是一个例子:  

先编写接口Man:  

  public interface Man {  

      public String sayHello();  

}  

然后写Man的实现类Chinese和American:  

@Service 

public class Chinese implements Man{  

    public String sayHello() {  

        return "I am Chinese!";  

    }  

}  

 

@Service 

public class American implements Man{  

    public String sayHello() {  

        return "I am American!";  

    }  

}  

      @Service注释表示定义一个bean,自动根据bean的类名实例化一个首写字母为小写的bean,例如Chinese实例化为chinese,American实例化为american,如果需要自己改名字则:@Service("你自己改的bean名")。  

 

beans.xml  

<?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-2.5.xsd  

           http://www.springframework.org/schema/context  

           http://www.springframework.org/schema/context/spring-context-2.5.xsd">  

      <context:annotation-config/>  

      <context:component-scan base-package="testspring.main"/>  

</beans>  

在spring的配置文件里面只需要加上<context:annotation-config/>和<context:component-scan base-package="需要实现注入的类所在包"/>,可以使用base-package="*"表示全部的类。  

编写主类测试:  

@Service 

public class Main {  

    @Autowired 

    @Qualifier("chinese")  

    private Man man;  

 

    public static void main(String[] args) {  

        // TODO code application logic here  

        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");  

        Main main = (Main) ctx.getBean("main");  

        System.out.println(main.getMan().sayHello());  

    }  

 

    public Man getMan() {  

        return man;  

    }  

}  

 

在Man接口前面标上@Autowired和@Qualifier注释使得Man接口可以被容器注入,当Man接口存在两个实现类的时候必须指定其中一个来注入,使用实现类首字母小写的字符串来注入。否则可以省略,只写@Autowired   

 

**********************  

使用 Spring 2.5 注释驱动的 IoC 功能  

 

注释配置相对于 XML 配置具有很多的优势:  

 

它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作。如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO 的属性名、类型等信息,如果关系表字段和 PO 属性名、类型都一致,您甚至无需编写任务属性映射信息——因为这些信息都可以通过 Java 反射机制获取。   

注释和 Java 代码位于一个文件中,而 XML 配置采用独立的配置文件,大多数配置信息在程序开发完成后都不会调整,如果配置信息和 Java 代码放在一起,有助于增强程序的内聚性。而采用独立的 XML 配置文件,程序员在编写一个功能时,往往需要在程序文件和配置文件中不停切换,这种思维上的不连贯会降低开发效率。   

因此在很多情况下,注释配置比 XML 配置更受欢迎,注释配置有进一步流行的趋势。Spring 2.5 的一大增强就是引入了很多注释类,现在您已经可以使用注释配置完成大部分 XML 配置的功能。在这篇文章里,我们将向您讲述使用注释进行 Bean 定义和依赖注入的内容。  

 

原来我们是怎么做的  

 

在使用注释配置之前,先来回顾一下传统上是如何配置 Bean 并完成 Bean 之间依赖关系的建立。下面是 3 个类,它们分别是 Office、Car 和 Boss,这 3 个类需要在 Spring 容器中配置为 Bean:  

 

Office 仅有一个属性:  

 

 

清单 1. Office.java  

                  

package com.baobaotao;  

public class Office {  

    private String officeNo =”001”;  

 

    //省略 get/setter  

 

    @Override 

    public String toString() {  

        return "officeNo:" + officeNo;  

    }  

}  

   

 

 

Car 拥有两个属性:  

清单 2. Car.java  

                  

package com.baobaotao;  

 

public class Car {  

    private String brand;  

    private double price;  

     // 省略 get/setter  

      @Override 

    public String toString() {  

        return "brand:" + brand + "," + "price:" + price;  

    }  

}  

   

Boss 拥有 Office 和 Car 类型的两个属性:  

 

清单 3. Boss.java  

package com.baobaotao;  

public class Boss {  

    private Car car;  

    private Office office;  

     // 省略 get/setter  

     @Override 

    public String toString() {  

        return "car:" + car + "\n" + "office:" + office;  

    }  

}  

我们在 Spring 容器中将 Office 和 Car 声明为 Bean,并注入到 Boss Bean 中:下面是使用传统 XML 完成这个工作的配置文件 beans.xml:  

清单 4. beans.xml 将以上三个类配置成 Bean  

<?xml version="1.0" encoding="UTF-8" ?>  

<beans xmlns="http://www.springframework.org/schema/beans" 

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

    xsi:schemaLocation="http://www.springframework.org/schema/beans   

 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  

    <bean id="boss" class="com.baobaotao.Boss">  

        <property name="car" ref="car"/>  

        <property name="office" ref="office" />  

    </bean>  

    <bean id="office" class="com.baobaotao.Office">  

        <property name="officeNo" value="002"/>  

    </bean>  

    <bean id="car" class="com.baobaotao.Car" scope="singleton">  

        <property name="brand" value=" 红旗 CA72"/>  

        <property name="price" value="2000"/>  

    </bean>  

</beans>  

 

当我们运行以下代码时,控制台将正确打出 boss 的信息:  

 

清单 5. 测试类:AnnoIoCTest.java  

                  

import org.springframework.context.ApplicationContext;  

import org.springframework.context.support.ClassPathXmlApplicationContext;  

public class AnnoIoCTest {  

 

    public static void main(String[] args) {  

        String[] locations = {"beans.xml"};  

        ApplicationContext ctx =   

            new ClassPathXmlApplicationContext(locations);  

        Boss boss = (Boss) ctx.getBean("boss");  

        System.out.println(boss);  

    }  

}  

这说明 Spring 容器已经正确完成了 Bean 创建和装配的工作。  

使用 @Autowired 注释  

 

Spring 2.5 引入了 @Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。来看一下使用 @Autowired 进行成员变量自动注入的代码:  

清单 6. 使用 @Autowired 注释的 Boss.java  

                  

package com.baobaotao;  

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

 

public class Boss {  

 

    @Autowired 

    private Car car;  

 

    @Autowired 

    private Office office;  

 

    …  

}  

Spring 通过一个 BeanPostProcessor 对 @Autowired 进行解析,所以要让 @Autowired 起作用必须事先在 Spring 容器中声明 AutowiredAnnotationBeanPostProcessor Bean。  

清单 7. 让 @Autowired 注释工作起来  

                  

<?xml version="1.0" encoding="UTF-8" ?>  

<beans xmlns="http://www.springframework.org/schema/beans" 

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

    xsi:schemaLocation="http://www.springframework.org/schema/beans   

 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  

      <!-- 该 BeanPostProcessor 将自动起作用,对标注 @Autowired 的 Bean 进行自动注入 -->  

    <bean class="org.springframework.beans.factory.annotation.  

        AutowiredAnnotationBeanPostProcessor"/>  

     <!-- 移除 boss Bean 的属性注入配置的信息 -->  

    <bean id="boss" class="com.baobaotao.Boss"/>  

       <bean id="office" class="com.baobaotao.Office">  

        <property name="officeNo" value="001"/>  

    </bean>  

    <bean id="car" class="com.baobaotao.Car" scope="singleton">  

        <property name="brand" value=" 红旗 CA72"/>  

        <property name="price" value="2000"/>  

    </bean>  

</beans>  

这样,当 Spring 容器启动时,AutowiredAnnotationBeanPostProcessor 将扫描 Spring 容器中所有 Bean,当发现 Bean 中拥有 @Autowired 注释时就找到和其匹配(默认按类型匹配)的 Bean,并注入到对应的地方中去。  

按照上面的配置,Spring 将直接采用 Java 反射机制对 Boss 中的 car 和 office 这两个私有成员变量进行自动注入。所以对成员变量使用 @Autowired 后,您大可将它们的 setter 方法(setCar() 和 setOffice())从 Boss 中删除。  

 当然,您也可以通过 @Autowired 对方法或构造函数进行标注,来看下面的代码:  

清单 8. 将 @Autowired 注释标注在 Setter 方法上  

                  

package com.baobaotao;  

 

public class Boss {  

    private Car car;  

    private Office office;  

 

     @Autowired 

    public void setCar(Car car) {  

        this.car = car;  

    }  

   

    @Autowired 

    public void setOffice(Office office) {  

        this.office = office;  

    }  

    …  

}  

 

这时,@Autowired 将查找被标注的方法的入参类型的 Bean,并调用方法自动注入这些 Bean。而下面的使用方法则对构造函数进行标注:  

 

清单 9. 将 @Autowired 注释标注在构造函数上  

                  

package com.baobaotao;  

 

public class Boss {  

    private Car car;  

    private Office office;  

   

    @Autowired 

    public Boss(Car car ,Office office){   

        this.car = car;  

        this.office = office ;  

    }  

   

    …  

}  

 

由于 Boss() 构造函数有两个入参,分别是 car 和 office,@Autowired 将分别寻找和它们类型匹配的 Bean,将它们作为 Boss(Car car ,Office office) 的入参来创建 Boss Bean。  

 

 

当候选 Bean 数目不为 1 时的应对方法  

 

在默认情况下使用 @Autowired 注释进行自动注入时,Spring 容器中匹配的候选 Bean 数目必须有且仅有一个。当找不到一个匹配的 Bean 时,Spring 容器将抛出 BeanCreationException 异常,并指出必须至少拥有一个匹配的 Bean。我们可以来做一个实验:  

 

清单 10. 候选 Bean 数目为 0 时  

                  

<?xml version="1.0" encoding="UTF-8" ?>  

<beans xmlns="http://www.springframework.org/schema/beans" 

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

     xsi:schemaLocation="http://www.springframework.org/schema/beans   

 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd ">  

   

    <bean class="org.springframework.beans.factory.annotation.  

        AutowiredAnnotationBeanPostProcessor"/>   

 

    <bean id="boss" class="com.baobaotao.Boss"/>  

 

    <!-- 将 office Bean 注释掉 -->  

    <!-- <bean id="office" class="com.baobaotao.Office">  

    <property name="officeNo" value="001"/>  

    </bean>-->  

 

    <bean id="car" class="com.baobaotao.Car" scope="singleton">  

        <property name="brand" value=" 红旗 CA72"/>  

        <property name="price" value="2000"/>  

    </bean>  

</beans>  

 

由于 office Bean 被注释掉了,所以 Spring 容器中将没有类型为 Office 的 Bean 了,而 Boss 的 office 属性标注了 @Autowired,当启动 Spring 容器时,异常就产生了。  

 

当不能确定 Spring 容器中一定拥有某个类的 Bean 时,可以在需要自动注入该类 Bean 的地方可以使用 @Autowired(required = false),这等于告诉 Spring:在找不到匹配 Bean 时也不报错。来看一下具体的例子:  

 

清单 11. 使用 @Autowired(required = false)  

                  

package com.baobaotao;  

 

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

import org.springframework.beans.factory.annotation.Required;  

 

public class Boss {  

 

    private Car car;  

    private Office office;  

 

    @Autowired 

    public void setCar(Car car) {  

        this.car = car;  

    }  

    @Autowired(required = false)  

    public void setOffice(Office office) {  

        this.office = office;  

    }  

    …  

}  

   

 

 

当然,一般情况下,使用 @Autowired 的地方都是需要注入 Bean 的,使用了自动注入而又允许不注入的情况一般仅会在开发期或测试期碰到(如为了快速启动 Spring 容器,仅引入一些模块的 Spring 配置文件),所以 @Autowired(required = false) 会很少用到。  

 

和找不到一个类型匹配 Bean 相反的一个错误是:如果 Spring 容器中拥有多个候选 Bean,Spring 容器在启动时也会抛出 BeanCreationException 异常。来看下面的例子:  

 

清单 12. 在 beans.xml 中配置两个 Office 类型的 Bean  

                  

…   

<bean id="office" class="com.baobaotao.Office">  

    <property name="officeNo" value="001"/>  

</bean>  

<bean id="office2" class="com.baobaotao.Office">  

    <property name="officeNo" value="001"/>  

</bean>  

…  

 

我们在 Spring 容器中配置了两个类型为 Office 类型的 Bean,当对 Boss 的 office 成员变量进行自动注入时,Spring 容器将无法确定到底要用哪一个 Bean,因此异常发生了。  

 

Spring 允许我们通过 @Qualifier 注释指定注入 Bean 的名称,这样歧义就消除了,可以通过下面的方法解决异常:  

 

 

清单 13. 使用 @Qualifier 注释指定注入 Bean 的名称  

                  

@Autowired 

public void setOffice(@Qualifier("office")Office office) {  

    this.office = office;  

}  

   

 

 

@Qualifier("office") 中的 office 是 Bean 的名称,所以 @Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了。@Autowired 可以对成员变量、方法以及构造函数进行注释,而 @Qualifier 的标注对象是成员变量、方法入参、构造函数入参。正是由于注释对象的不同,所以 Spring 不将 @Autowired 和 @Qualifier 统一成一个注释类。下面是对成员变量和构造函数入参进行注释的代码:   

 

对成员变量进行注释:  

 

 

清单 14. 对成员变量使用 @Qualifier 注释  

                  

public class Boss {  

    @Autowired 

    private Car car;  

   

    @Autowired 

    @Qualifier("office")  

    private Office office;  

    …  

}  

对构造函数入参进行注释:  

清单 15. 对构造函数变量使用 @Qualifier 注释  

                  

public class Boss {  

    private Car car;  

    private Office office;  

 

    @Autowired 

    public Boss(Car car , @Qualifier("office")Office office){  

        this.car = car;  

        this.office = office ;  

    }  

}  

   

 

@Qualifier 只能和 @Autowired 结合使用,是对 @Autowired 有益的补充。一般来讲,@Qualifier 对方法签名中入参进行注释会降低代码的可读性,而对成员变量注释则相对好一些。  

使用 JSR-250 的注释  

 

Spring 不但支持自己定义的 @Autowired 的注释,还支持几个由 JSR-250 规范定义的注释,它们分别是 @Resource、@PostConstruct 以及 @PreDestroy。  

 

@Resource 

 

@Resource 的作用相当于 @Autowired,只不过 @Autowired 按 byType 自动注入,面 @Resource 默认按 byName 自动注入罢了。@Resource 有两个属性是比较重要的,分别是 name 和 type,Spring 将 @Resource 注释的 name 属性解析为 Bean 的名字,而 type 属性则解析为 Bean 的类型。所以如果使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略。如果既不指定 name 也不指定 type 属性,这时将通过反射机制使用 byName 自动注入策略。  

 

Resource 注释类位于 Spring 发布包的 lib/j2ee/common-annotations.jar 类包中,因此在使用之前必须将其加入到项目的类库中。来看一个使用 @Resource 的例子:  

 

 

清单 16. 使用 @Resource 注释的 Boss.java  

                  

package com.baobaotao;  

 

import javax.annotation.Resource;  

 

public class Boss {  

    // 自动注入类型为 Car 的 Bean  

    @Resource 

    private Car car;  

 

    // 自动注入 bean 名称为 office 的 Bean  

    @Resource(name = "office")  

    private Office office;  

}  

一般情况下,我们无需使用类似于 @Resource(type=Car.class) 的注释方式,因为 Bean 的类型信息可以通过 Java 反射从代码中获取。  

 

要让 JSR-250 的注释生效,除了在 Bean 类中标注这些注释外,还需要在 Spring 容器中注册一个负责处理这些注释的 BeanPostProcessor:  

 

<bean    class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>  

 

CommonAnnotationBeanPostProcessor 实现了 BeanPostProcessor 接口,它负责扫描使用了 JSR-250 注释的 Bean,并对它们进行相应的操作。  

 @PostConstruct 和 @PreDestroy 

  Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,您既可以通过实现 InitializingBean/DisposableBean 接口来定制初始化之后 / 销毁之前的操作方法,也可以通过 <bean> 元素的 init-method/destroy-method 属性指定初始化之后 / 销毁之前调用的操作方法。关于 Spring 的生命周期,笔者在《精通 Spring 2.x—企业应用开发精解》第 3 章进行了详细的描述,有兴趣的读者可以查阅。  

  JSR-250 为初始化之后/销毁之前方法的指定定义了两个注释类,分别是 @PostConstruct 和 @PreDestroy,这两个注释只能应用于方法上。标注了 @PostConstruct 注释的方法将在类实例化后调用,而标注了 @PreDestroy 的方法将在类销毁之前调用。  

 

 

清单 17. 使用 @PostConstruct 和 @PreDestroy 注释的 Boss.java  

                  

package com.baobaotao;  

 

import javax.annotation.Resource;  

import javax.annotation.PostConstruct;  

import javax.annotation.PreDestroy;  

 

public class Boss {  

    @Resource 

    private Car car;  

 

    @Resource(name = "office")  

    private Office office;  

 

    @PostConstruct 

    public void postConstruct1(){  

        System.out.println("postConstruct1");  

    }  

 

    @PreDestroy 

    public void preDestroy1(){  

        System.out.println("preDestroy1");   

    }  

    …  

}  

   

 

 

您只需要在方法前标注 @PostConstruct 或 @PreDestroy,这些方法就会在 Bean 初始化后或销毁之前被 Spring 容器执行了。  

 

我们知道,不管是通过实现 InitializingBean/DisposableBean 接口,还是通过 <bean> 元素的 init-method/destroy-method 属性进行配置,都只能为 Bean 指定一个初始化 / 销毁的方法。但是使用 @PostConstruct 和 @PreDestroy 注释却可以指定多个初始化 / 销毁方法,那些被标注 @PostConstruct 或 @PreDestroy 注释的方法都会在初始化 / 销毁时被执行。   

 

通过以下的测试代码,您将可以看到 Bean 的初始化 / 销毁方法是如何被执行的:  

 

清单 18. 测试类代码  

                  

package com.baobaotao;  

 

import org.springframework.context.support.ClassPathXmlApplicationContext;  

 

public class AnnoIoCTest {  

 

    public static void main(String[] args) {  

        String[] locations = {"beans.xml"};  

        ClassPathXmlApplicationContext ctx =   

            new ClassPathXmlApplicationContext(locations);  

        Boss boss = (Boss) ctx.getBean("boss");  

        System.out.println(boss);  

        ctx.destroy();// 关闭 Spring 容器,以触发 Bean 销毁方法的执行  

    }  

}  

 

这时,您将看到标注了 @PostConstruct 的 postConstruct1() 方法将在 Spring 容器启动时,创建 Boss Bean 的时候被触发执行,而标注了 @PreDestroy 注释的 preDestroy1() 方法将在 Spring 容器关闭前销毁 Boss Bean 的时候被触发执行。  

使用 <context:annotation-config/> 简化配置  

 

Spring 2.1 添加了一个新的 context 的 Schema 命名空间,该命名空间对注释驱动、属性文件引入、加载期织入等功能提供了便捷的配置。我们知道注释本身是不会做任何事情的,它仅提供元数据信息。要使元数据信息真正起作用,必须让负责处理这些元数据的处理器工作起来。   

 

而我们前面所介绍的 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor 就是处理这些注释元数据的处理器。但是直接在 Spring 配置文件中定义这些 Bean 显得比较笨拙。Spring 为我们提供了一种方便的注册这些 BeanPostProcessor 的方式,这就是 <context:annotation-config/>。请看下面的配置:  

 

 

清单 19. 调整 beans.xml 配置文件  

                  

<?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-2.5.xsd  

 http://www.springframework.org/schema/context   

 http://www.springframework.org/schema/context/spring-context-2.5.xsd">  

   

    <context:annotation-config/>   

 

    <bean id="boss" class="com.baobaotao.Boss"/>  

    <bean id="office" class="com.baobaotao.Office">  

        <property name="officeNo" value="001"/>  

    </bean>  

    <bean id="car" class="com.baobaotao.Car" scope="singleton">  

        <property name="brand" value=" 红旗 CA72"/>  

        <property name="price" value="2000"/>  

    </bean>  

</beans>  

<context:annotationconfig/> 将隐式地向 Spring 容器注册 AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor 以及 equiredAnnotationBeanPostProcessor 这 4 个 BeanPostProcessor。    

在配置文件中使用 context 命名空间之前,必须在 <beans> 元素中声明 context 命名空间。  

使用 @Component 

  虽然我们可以通过 @Autowired 或 @Resource 在 Bean 类中使用自动注入功能,但是 Bean 还是在 XML 文件中通过 <bean> 进行定义 —— 也就是说,在 XML 配置文件中定义 Bean,通过 @Autowired 或 @Resource 为 Bean 的成员变量、方法入参或构造函数入参提供自动注入的功能。能否也通过注释定义 Bean,从 XML 配置文件中完全移除 Bean 定义的配置呢?答案是肯定的,我们通过 Spring 2.5 提供的 @Component 注释就可以达到这个目标了。  

  下面,我们完全使用注释定义 Bean 并完成 Bean 之间装配:  

清单 20. 使用 @Component 注释的 Car.java  

                  

package com.baobaotao;  

  import org.springframework.stereotype.Component;  

  @Component 

public class Car {  

    …  

}  

 

仅需要在类定义处,使用 @Component 注释就可以将一个类定义了 Spring 容器中的 Bean。下面的代码将 Office 定义为一个 Bean:  

 

清单 21. 使用 @Component 注释的 Office.java                     

package com.baobaotao;  

 import org.springframework.stereotype.Component;  

  

@Component 

public class Office {  

    private String officeNo = "001";  

    …  

}

这样,我们就可以在 Boss 类中通过 @Autowired 注入前面定义的 Car 和 Office Bean 了。  

 

清单 22. 使用 @Component 注释的 Boss.java  

                  

package com.baobaotao;  

 

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

import org.springframework.beans.factory.annotation.Required;  

import org.springframework.beans.factory.annotation.Qualifier;  

import org.springframework.stereotype.Component;  

 

@Component("boss")  

public class Boss {  

    @Autowired 

    private Car car;  

 

    @Autowired 

    private Office office;  

    …  

}  

@Component 有一个可选的入参,用于指定 Bean 的名称,在 Boss 中,我们就将 Bean 名称定义为“boss”。一般情况下,Bean 都是 singleton 的,需要注入 Bean 的地方仅需要通过 byType 策略就可以自动注入了,所以大可不必指定 Bean 的名称。  

  在使用 @Component 注释后,Spring 容器必须启用类扫描机制以启用注释驱动 Bean 定义和注释驱动 Bean 自动注入的策略。Spring 2.5 对 context 命名空间进行了扩展,提供了这一功能,请看下面的配置:  

清单 23. 简化版的 beans.xml  

                  

<?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-2.5.xsd  

 http://www.springframework.org/schema/context   

 http://www.springframework.org/schema/context/spring-context-2.5.xsd">  

    <context:component-scan base-package="com.baobaotao"/>  

</beans>   

 

这里,所有通过 <bean> 元素定义 Bean 的配置内容已经被移除,仅需要添加一行 <context:component-scan/> 配置就解决所有问题了——Spring XML 配置文件得到了极致的简化(当然配置元数据还是需要的,只不过以注释形式存在罢了)。<context:component-scan/> 的 base-package 属性指定了需要扫描的类包,类包及其递归子包中所有的类都会被处理。  

 

<context:component-scan/> 还允许定义过滤器将基包下的某些类纳入或排除。Spring 支持以下 4 种类型的过滤方式,通过下表说明:  

 

表 1. 扫描过滤方式  

过滤器类型 说明   

注释 假如 com.baobaotao.SomeAnnotation 是一个注释类,我们可以将使用该注释的类过滤出来。   

类名指定 通过全限定类名进行过滤,如您可以指定将 com.baobaotao.Boss 纳入扫描,而将 com.baobaotao.Car 排除在外。   

正则表达式 通过正则表达式定义过滤的类,如下所示: com\.baobaotao\.Default.*   

AspectJ 表达式 通过 AspectJ 表达式定义过滤的类,如下所示: com. baobaotao..*Service+   

 

下面是一个简单的例子:  

 

<context:component-scan base-package="com.baobaotao">  

    <context:include-filter type="regex"   

        expression="com\.baobaotao\.service\..*"/>  

    <context:exclude-filter type="aspectj"   

        expression="com.baobaotao.util..*"/>  

</context:component-scan>  

值得注意的是 <context:component-scan/> 配置项不但启用了对类包进行扫描以实施注释驱动 Bean 定义的功能,同时还启用了注释驱动自动注入的功能(即还隐式地在内部注册了 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor),因此当使用 <context:component-scan/> 后,就可以将 <context:annotation-config/> 移除了。  

 

默认情况下通过 @Component 定义的 Bean 都是 singleton 的,如果需要使用其它作用范围的 Bean,可以通过 @Scope 注释来达到目标,如以下代码所示:  

清单 24. 通过 @Scope 指定 Bean 的作用范围  

                  

package com.baobaotao;  

import org.springframework.context.annotation.Scope;  

…  

@Scope("prototype")  

@Component("boss")  

public class Boss {  

    …  

}  

这样,当从 Spring 容器中获取 boss Bean 时,每次返回的都是新的实例了。  

采用具有特殊语义的注释  

 

Spring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository、@Service 和 @Controller。在目前的 Spring 版本中,这 3 个注释和 @Component 是等效的,但是从注释类的命名上,很容易看出这 3 个注释分别和持久层、业务层和控制层(Web 层)相对应。虽然目前这 3 个注释和 @Component 相比没有什么新意,但 Spring 将在以后的版本中为它们添加特殊的功能。所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用 @Repository、@Service 和 @Controller 对分层中的类进行注释,而用 @Component 对那些比较中立的类进行注释。  

注释配置和 XML 配置的适用场合  

 

是否有了这些 IOC 注释,我们就可以完全摒除原来 XML 配置的方式呢?答案是否定的。有以下几点原因:  

 

注释配置不一定在先天上优于 XML 配置。如果 Bean 的依赖关系是固定的,(如 Service 使用了哪几个 DAO 类),这种配置信息不会在部署时发生调整,那么注释配置优于 XML 配置;反之如果这种依赖关系会在部署时发生调整,XML 配置显然又优于注释配置,因为注释是对 Java 源代码的调整,您需要重新改写源代码并重新编译才可以实施调整。   

如果 Bean 不是自己编写的类(如 JdbcTemplate、SessionFactoryBean 等),注释配置将无法实施,此时 XML 配置是唯一可用的方式。   

注释配置往往是类级别的,而 XML 配置则可以表现得更加灵活。比如相比于 @Transaction 事务注释,使用 aop/tx 命名空间的事务配置更加灵活和简单。   

所以在实现应用中,我们往往需要同时使用注释配置和 XML 配置,对于类级别且不会发生变动的配置可以优先考虑注释配置;而对于那些第三方类以及容易发生调整的配置则应优先考虑使用 XML 配置。Spring 会在具体实施 Bean 创建和 Bean 注入之前将这两种配置方式的元信息融合在一起。  

小结  

  Spring 在 2.1 以后对注释配置提供了强力的支持,注释配置功能成为 Spring 2.5 的最大的亮点之一。合理地使用 Spring 2.5 的注释配置,可以有效减少配置的工作量,提高程序的内聚性。但是这并不意味着传统 XML 配置将走向消亡,在第三方类 Bean 的配置,以及那些诸如数据源、缓存池、持久层操作模板类、事务管理等内容的配置上,XML 配置依然拥有不可替代的地位。

 

 

 

 

 

 

GEE开发之ERA5(气温、降水、压力、风速等)数据获取和分析 前言:ERA5主要提供DAILY和MONTHLY两大类别数据,其中主要包括气温、降水、压力、风速等。 阅读详情

相关推荐

HDMI设计6--Video PHY Controller IP

Reference:https://china.xilinx.com/content/dam/xilinx/support/documentation/ip_documentation/vid_phy_controller/v2_2/pg230-vid-phy-controller.pdf 1. 序 Video PHY Controller IP是为实现与视频(DisplayPort和HDMI™技术)MAC传输或接收子系统的即插即用连接而设计的。视频MAC层和PHY层的接口是标准化的,能...

Archar_Saber的博客 8340

Spring Boot 学习--01.依赖注入@Compenent@Autowired

Spring Boot 学习–01.依赖注入 @Component@Autowired 依赖注入是Spring Boot里非常重要的特性,Dependency Injection。这里的例子是《深入浅出Spring boot2.x》中的例子。 任务说明 人可以通过动物来完成某些工作,比如让狗守门,猫抓老鼠。那么如何来建立他们的关系,即依赖注入呢 注解说明 @Component 装配,用处是表明这个...

kingsirvince的博客 1381

PHP+MYSQL宠物主题动态网页设计源码+数据库,大学生期末大作业,PHP课程设计

PHP+MYSQL宠物主题动态网页设计源码+数据库,大学生期末大作业,PHP课程设计提示:本文采用PHP对数据库进行操作:本文就介绍了PHP实现对MySQL数据库的增删改查操作基础内容。

900

使用 Spring 2.5 注释驱动的 IoC 功能

概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作。如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO 的属性名、类型等信息,如果关系表字段和 PO 属性名、类型都一致,您甚至无需编写任务属性映射信息——因为这些信息都可以通过 Java 反射机制获取。 注释和 Java 代码位于一个文...

guoli83945的专栏 278

正点原子stm32f103RChal库制作数字秒表:如用keil5和正点原子STM32F1开发板实现?

🏆本文收录于 《全栈Bug调优(实战版)》 专栏,该专栏专注于分享我在真实项目开发中遇到的各类疑难Bug及其深层成因,并系统提供高效、可复现的解决思路和实操方案。无论你是刚入行的新手开发者,还是拥有多年项目经验的资深工程师,本专栏都将为你提供一条系统化、高质量的问题排查与优化路径,助力你加速成长,攻克技术壁垒,迈向技术价值最大化与职业发展的更高峰🚀!    📌 特别说明: 文中部分技术问题来源于真实生产环境及网络公开案例,均经过精挑细选与系统化整理,并结合多位一线资深架构师和工程师多年实战经验沉淀,提

**My Coding Family** 1264

OpenClaw 预置技能完全指南

OpenClaw 技能(Skills)是扩展 AI 助手能力的插件系统。🔐 管理密码和敏感信息(1Password)📝 操作 Apple Notes 和 Reminders🔍 实时搜索互联网(Brave Search)🎨 生成和编辑图片(Nano Banana Pro)📧 收发邮件(Himalaya)🏠 控制智能家居(OpenHue、Eight Sleep)💬 发送消息(iMessage、WhatsApp、Slack)🎵 控制音乐播放(Spotify、Sonos)

Maynor的博客 1703

【spring】@Component注解学习

Component 是 Spring 框架中的一个注解,用于将一个类标记为 Spring 上下文中的一个组件。当一个类被标记为 @Component 时,Spring 容器会在启动时自动扫描并实例化这个类,并将其注册到 Spring 上下文中。@Component 注解可以用于任何类,包括控制器、服务、DAO 等。当一个类被标记为 @Component 时,它就成为了 Spring 上下文中的一个 bean,可以被其他 bean 通过依赖注入的方式使用。

一个写了10年bug的程序员日常笔记。 3709

26、机器学习模型的成员推断攻击与隐私保护

本文探讨了机器学习模型面临的成员推断攻击及其对隐私的潜在威胁。通过使用CIFAR-10数据集,详细介绍了如何利用影子模型和攻击模型推断特定数据点是否属于模型的训练集。实验表明,即使无法直接访问模型参数和原始数据,攻击者仍能以高于随机猜测的概率进行推断,从而构成隐私风险。此外,文章还分析了实验的关键技术点,并提出了多种隐私保护建议,包括数据脱敏、差分隐私、模型正则化等方法。

coffee的博客 123

JavaEE-day21-Spring-使用注解实现IOC

注解方式可以将Bean的定义信息和Bean实现类结合在一起,Spring提供的注解有: @Component:实现Bean组件的定义。 @Repository :用于标注DAO类。 @Service :用于标注业务类。 @Controller :用于标注控制器类。 1.例如以下代码,指明userDao是UserDaoImpl的实例名称: @Repository("userDao") public class UserDaoImpl implements UserDao { … } 上述与在XML配

徐xx的博客 247

AI上推荐 之 协同过滤

㐇

Miracle8070 1万+

YOLOv13改进策略【YOLO和Mamba】| 替换骨干 Mamba-YOLOv13-T !!! 最新的发文热点

模块是模型中的一个重要组成部分,其主要作用是在模型的初始阶段对输入图像进行处理,方便后续的特征提取和目标检测。以下是对。

Limiiiing的博客 353

【Spring】IOC理解

关于IOC,有如下几点疑问: 什么是IOC IOC和@autowired IOC和依赖注入有何关联 一、什么是IOC 所谓 IOC ,“控制反转”,就是由 Spring IOC 容器来负责对象的生命周期和对象之间的关系,通俗的讲,就是原来需要手动使用new来创建对象,后面交个IOC容器来控制了。 IOC是一种思想,不是技术。 谁控制谁:在传统的开发模式下,我们都是采用直接 new 一个对象的方式来创建对象,也就是说你依赖的对象直接由你自己控制,但是有了 IOC 容器后,则直接由 IoC 容器来控

依步_的专栏 536

uniapp H5刷新页面后返回按钮失效问题完美解决方案

这个问题其实很隐蔽,尤其是uniapp H5 场景下刷新导致栈清理,很多开发者一开始都懵掉了。uniapp 内部对「页面栈只有一个」时的返回逻辑是reLaunch;所以只要在这个分支里替换为自己的逻辑(比如),就能顺利实现预期。目前我在项目里已经跑通了,暂时没发现问题。不得不说,知道源码里这个逻辑后,真的是醍醐灌顶,只能膜拜框架大佬了 🤯。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 524

Spring之注解开发

Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率。

write less , do more 6320

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Spring——基于注解的配置

Spring注解配置 从 Spring 2.5 开始就可以使用注解来配置依赖注入。使用注解的方式使我们无需在XML中配置一个Bean引用,更加简单和方便。 注解配置默认情况下在Spring中是关闭的,我们需要在配置文件中使用&lt;context:annotation-config/&gt;激活它。 如下spring-config.xml文件: &lt;?xml version="1....

Gavin 2万+

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Spring的注解 @Bean用法

随着SpringBoot的流行,基于注解式开发的热潮逐渐覆盖了基于XML纯配置的开发,而作为Spring中最核心的bean当然也能够使用注解的方式进行表示。所以本篇就来详细的讨论一下作为Spring中的Bean到底都有哪些用法。 @Bean 基础声明 Spring的@Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中。 S

应无所住而生其心 2万+

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Spring注解

1.声明bean的注解 Spring注解 描述 @Component 组件,没有明确的角色 @Service 在业务逻辑层使用(service层) @Repository 在展现层使用,控制器的声明(C) @Controller 定义文档的主体 2.注入bean的注解 Spring注解 描述 @Autowired Spring提供的工具(由Spring的依赖注入工具(BeanPostProcess...

console_log_LGA的博客 2096

Spring 中的常用注解

Spring 作为 Java 企业级开发中最广泛使用的框架之一,以其强大的功能和灵活性为开发者提供了高效的开发体验。在 Spring 中,注解(Annotation)是其核心机制之一,它简化了配置文件的繁琐操作,通过声明的方式实现了依赖注入等功能。本篇文章将介绍 Spring 框架中一些常用的注解,并结合实际场景详细说明它们的使用方法与作用。这不仅可以帮助初学者快速掌握 Spring 的基本用法,也能为有经验的开发者提供一个参考,帮助在实际开发中更高效地使用这些工具。

栗筝i的博客 2510

Spring 注解解析

@Transactional 通过 AOP 动态代理和 事务管理器实现声明式事务管理,开发者需关注传播行为、隔离级别、异常处理等核心属性,避免同类调用、非 public 方法等失效场景。在复杂场景下,结合编程式事务可提升灵活性和可控性。

肢解生活,直达本质;凡所有相,皆是虚妄。 1781

Spring 中所有注解

Spring中的注解主要分为两类: 类级别的注解:如@Component、@Repository、@Controller、@Service以及JavaEE6的@ManagedBean和@Named注解,都是添加在类上面的类级别注解。 类内部的注解:如@Autowire、@Value、@Resource以及EJB和WebService相关的注解等,都是添加在类内部的字段或者方法上的类内部注解。 ...

weixin_44371237的博客 2541

Spring注解开发

Spring IoC注解式开发通过使用注解来简化XML配置,Spring6倡导全注解开发。注解的定义和使用包括定义注解及其属性、使用注解以及通过反射机制读取注解。常见的声明Bean的注解有@Component、@Controller、@Service和@Repository。通过反射机制,可以扫描指定包下的类,判断类上是否有特定注解,并实例化相应的对象。这种方式使得开发更加简洁和高效,减少了繁琐的XML配置。

weixin_63855746的博客 880

Spring常用注解全集

第一个是,@Target,表明注解所修饰的对象范围,即,该注解可以用在哪里。第二个是,@Retention,表示注解被保留的时间长短,也就是注解的生命周期。

m0_73413202的博客 1344

【Spring】Spring注解大全

1. 注解是什么? 其实 Java 的注解还是特别常见的,像平时用到的 @Override、@Deprecated 等都是注解的一种表现方式。 对于注解官方解释:为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后的某个时刻非常方便地使用这些数据。 2. 注解作用 可以书写更加干净易读的代码,简化重复的工作,比如 Spring 的注解; 另外还提供编译期类型检查,比如外汇...

小七的博客 920

注解及Spring系列注解

1.定义:使用@interface2.定义属性:类名+名字()3.赋默认值:default + 默认值4.修饰:使用需要的元注解注解为代码提供元数据,用于标记、约束、文档化和框架集成,可被编译器或运行时处理。熟练运用注解,可以提高开发的效率。

m0_75014903的博客 1129
上一篇: hibernate的各种保存方式的区别 (save,persist,update,saveOrUpdte,merge,flush,lock)等
下一篇: JQuery和Struts实现Ajax文件上传
lb8607
博客等级 码龄18年 17粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lb8607

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值