Spring之常见注解

本文阅读 11 分钟
首页 代码,Java 正文

注解在其声明中提供了大量上下文,从而导致更短更简洁的配置。XML 擅长在不触及源代码或重新编译它们的情况下连接组件。 spring 中的注解和 xml 配置,以及所谓的 java 配置类,最终将在 spring ioc 容器内,被表示为 BeanDefinition 对象、环境对象、 profile 等相关的其它对象实例。

XML和注解的区别:

  • 注解:是一种分散式的元数据,与源代码紧绑定
  • xml:是一种集中式的元数据,与源代码无绑定
  • 让 xm 有用的是使用 xml 的类,同样让注解有效的是注解处理器 ,否则注解和注释没什么区别
  • 注解这种机制是一种与 Java 编程语言无关的独立存在,它会让 java 语言更好,但不是语言必须的部分

Spring 3.0新增了另外两个实现类:AnnotationConfigApplicationContext 和 AnnotationConfigWebApplicationContext。它们为注解而生,直接依赖于注解作为容器配置信息来源的IoC容器初始化类。AnnotationConfigWebApplicationContext是AnnotationConfigApplicationContext的web版本,两者用法几乎没有什么差别。官方文档描述:用@Configuration注释类表明其主要目的是作为bean定义的源,@Configuration类允许通过调用同一类中的其他@Bean方法来定义bean之间的依赖关系。通俗来说,@Configuration相当于之前XML配置中的< beans >,而@Bean相当于< bean >。

@Configuration注解

被@Configuration注解的类注意事项

  • 配置类不能是 final 类(没法动态代理)。
  • 配置类必须是非本地的(即不能将配置类定义在其他类的方法内部,不能是private)。
  • 配置类必须有一个无参构造函数。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {

    String value() default "";
}

@Bean注解

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {

    @AliasFor("name")
    String[] value() default {};

    @AliasFor("value")
    String[] name() default {};

    Autowire autowire() default Autowire.NO;

    String initMethod() default "";

    String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
}

@Bean包含的属性:

  • name :指定一个或者多个Bean的名字。等价于XML配置中的name属性,示例中的 @Bean (name = “oracleDataSource”)。
  • initMethod:容器在初始化完Bean之后,会调用该属性指定的方法。等价于XML配置中的init-method属性。
  • destroyMethod:该属性与initMethod功能相似,在容器销毁Bean之前,会调用该属性指定的方法。等价于XML配置中的destroy-method属性。
  • autowire:指定Bean属性的自动装配策略,取值是Autowire类型的三个静态属性。Autowire.BY_NAME,Autowire.BY_TYPE,Autowire.NO。与XML配置中的autowire属性的取值相比,少了constructor,因为 constructor在这里已经没有意义了。

被@Bean注解的类注意事项

  • @Bean 默认是单例模式,并且没有提供指定作用域的属性,可以通过 @Scope 来实现该功能。

有人可能会疑惑,@Configuration是如何被Spring纳入注解管理的,这是因为当配置完Spring扫描指定包及其子包中的类时,虽然只会扫描带有@Component 注解的类,但由于 @Configuration 注解本身也用 @Component 标注了,所以Spring能够识别出被 @Configuration 标注类。

使用方式如下:

@Configuration 
public class DataSourceConfig { 
    @Bean 
    public MysqlDataSource mysqlDataSource() { 
        return new MysqlDataSource();
     } 
     
    @Bean(name = "oracleDataSource") 
    public OracleDataSource oracleDataSource() {
         return new OracleDataSource(); 
     } 
    
    @Bean
    public OracleDataSource getCat() {
         return new Cat(); 
     } 
    
    @Bean(name = "oracleDataSource") 
    public OracleDataSource getBigCat() {
         getCat();
         return new BigCat(); 
     } 
 }

如上面所示,使用 @Configuration 来进行注解表示这个类可以使用Spring IoC容器作为bean定义的来源。 @Bean 注解在该类的方法上,AnnotationConfigApplicationContext将配置类中标注了 @Bean 的方法的返回值识别为Spring Bean,并注册到容器中,归入IoC容器管理,此时在IOC容器中每种类型只存在一个Bean实例

注意如果去掉@Configuration注解,@Bean的功能仍然存在,只是在每次调用被@Bean注解的方式时都会重新生成一个bean实例。例如,上面的例子中如果去掉@Configuration注解,那么在IOC容器中就会存在两个Cat实例。

被@Configuration注解与否为什么会出现这种差异呢?这就需要了解有关@Configuration注解的具体实现逻辑了,详见 @Configuration注解详解 spring中@Configuration注解的作用

官方文档描述:带@Component注解的类被看作组件,当使用基于注解的配置和类路径扫描的时候,这些被@Component注解的类就会被实例化。而诸如@Controller、@Service、@Repository 、@Aspect这些类级别的注解可以被认定为是@Component注解的特化,它们是由@Component注解的类注解,属于@Component注解的衍生注解,这些特化的注解主要用于更具体的用例,例如:分别在表示层、服务层和持久性层中使用。

所以< context:component-scan />虽然只扫描被@Component注解的类,但是它的衍生注解本身用@Component注释,所以被这些衍生注解所注解的类仍然会被扫描,并注册到IOC容器中称为一个Bean实例。

@Component注解

它将 java 类标记为 bean,是任何 Spring 管理组件的通用构造型。web开发中,提供3个@Component注解的衍生注解(功能一样)取代:

  • @Controller(“名称”):web层
  • @Service(“名称”):service层
  • @Repository(“名称”):dao层

问题:@Component和@Bean有什么区别? 答:@component 和 它的衍生注解(@controller, @service and @repository)都是注释在类上。告诉spring,此类是一个bean,通过类路径扫描自动检测并注入到spring容器中。 @bean不能注释在类上,只能用于在配置类中显式声明单个bean。意思就是我们想要获取这个bean的时候,spring要按照这种方式去获取这个bean。默认情况下@bean注释的方法名作为对象的名字,也可以用name属性定义对象的名字。

@Controller注解

它是@Component 注解的特化,它将一个类标记为 Spring Web MVC 控制器。标有它的 Bean 会自动导入到 IoC 容器中。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {

   String value() default "";
}

@Service注解

此注解是@Component 注解的特化,它不会对 @Component 注解提供任何其他行为。我们可以在服务层类中使用 @Service 而不是 @Component,因为它以更好的方式指明了意图。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {

    String value() default "";
}

@Repository注解

此注解是也是 @Component 注解的特化,它将 DAO 导入 IoC 容器,但它为 DAO 提供了额外的好处:使未经检查的异常有资格转换为 Spring DataAccessException。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {

    String value() default "";
}

这个注解表明bean的属性必须在配置的时候设置,通过一个bean定义的显式的属性值或通过自动装配,若@Required注解的bean属性未被设置,容器将抛出BeanInitializationException。如下:

public class Employee {
    private String name;
    @Required
    public void setName(String name){
        this.name=name;
    }
    public string getName(){
        return name;
    }
}

@Autowired注解

@Autowired属于Spring的注解,用于装配bean。此注解可单独使用,默认按照类型(byType)装配注入的,且默认情况下要求依赖对象必须存在,如果想要允许依赖对象为空,可以添加其属性required为false。如果使用@Autowired注解时想要通过bean的name来装配,就需要和@Qualifier注解配合使用了,通过@Qualifier指定bean的名称。

举例来说,如果一个接口有多个实现类,此时如果只使用@Autowired注解时就会报错,解决办法有两种:一、改用@Resource通过bean名称装配,二、通过@Autowired和@Qualifier配合使用来通过bean名称装配。

作用范围:构造函数、成员变量、方法(包括Setter方法)、参数甚至可以使用在注解上。如果写在字段上,那么就不需要再写setter方法了。

  • 使用在成员变量上
@Service
public class UserService {

    @Autowired
    private IUser user;
}
  • 使用在构造器上
@Service
public class UserService {

    private IUser user;

    @Autowired
    public UserService(IUser user) {
        this.user = user;
        System.out.println("user:" + user);
    }
}
  • 使用在方法上
@Service
public class UserService {

    @Autowired
    public void test(IUser user) {
       user.say();
    }
}

@Service
public class UserService {

    private IUser user;

    @Autowired
    public void setUser(IUser user) {
        this.user = user;
    }
}

spring会在项目启动的过程中,自动调用一次加了@Autowired注解的方法,我们可以在该方法做一些初始化的工作。

  • 使用在参数上
@Service
public class UserService {

    private IUser user;

    public UserService(@Autowired IUser user) {
        this.user = user;
        System.out.println("user:" + user);
    }
}

@Service
public class UserService {
    //也可以在非静态方法的入参上加Autowired注解
    public void test(@Autowired IUser user) {
       user.say();
    }
}

@Resource注解

@Resource不属于Spring的注解,属于Java EE的注解,以减少代码和Spring之间的耦合。此注解可以单独使用,默认通过byName的方式装配bean。@Resource中有两个属性:name和type,分别代表bean名称和bean类型,如果使用 name 属性,则使用 byName 的自动注入策略;如果使用 type 属性时则使用 byType 自动注入策略;如果既不指定 name 也不指定 type 属性,这时将通过反射机制使用 byName 自动注入策略(此时默认取字段名进行按照名称查找);如果同时指定name和 type,则从Spring上下文中找到唯一匹配进行装配,找不到抛出异常。

作用范围:成员变量、Setter方法,如果写在字段上,那么就不需要再写setter方法了。

@Qualifier注解

@Qualifier属于Spring的注解,属于更细粒度的指向,用于通过bean名称来装配对象。。用在字段上时,不能独立使用,通常和@Autowired注解配合使用;用在方法参数上时,可以独立使用。 作用范围:成员变量、Setter方法。

@Inject注解

@Inject不属于Spring的注解,属于JSR-330提供的注解,该规范主要提供Java注入相关的注解,需要手动引入:

<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>

此注解可以单独使用,默认通过类型(byType)进行自动装配,也可以和@Qualifier搭配使用

本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://blog.csdn.net/qq_38571892/article/details/123234372
-- 展开阅读全文 --
Web安全—逻辑越权漏洞(BAC)
« 上一篇 03-13
Redis底层数据结构--简单动态字符串
下一篇 » 04-10

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复