spring常用注解

1.1  spring常用注解

1.1.1            spring使用配置文件的问题

传统的spring是定义类和和类中定义成员类的引用和set、get接口。同时在配置文件中配置类和成员类之间的依赖关系。要传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事物,这么做有两个缺点:
1、如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么.xml文件又会非常多。总之这将导致配置文件的可读性与可维护性变得很低。
2、在开发中在.java文件和.xml文件之间不断切换,是一件麻烦的事,同时这种思维上的不连贯也会降低开发的效率。
为了解决这两个问题,Spring引入了注解,通过"@XXX"的方式,让注解与Java Bean紧密结合,既大大减少了配置文件的体积,又增加了Java Bean的可读性与内聚性。

不使用注解:

先看一个不使用注解的Spring示例,在这个示例的基础上,改成注解版本的,这样也能看出使用与不使用注解之间的区别,先定义一个老虎:

                       

package com.spring.model;

 

public class Tiger {

   

    private String tigerName="TigerKing";

   

    public String toString(){

        return "TigerName:"+tigerName;

    }

}

 

再定义一个猴子:

 

package com.spring.model;

 

public class Monkey {

   

    private String monkeyName = "MonkeyKing";

   

    public String toString(){

        return "MonkeyName:" + monkeyName;

    }

 

}

 

定义一个动物园:

 

package com.spring.model;

 

public class Zoo {

    private Tiger tiger;

    private Monkey monkey;

   

    public Tiger getTiger() {

        return tiger;

    }

    public void setTiger(Tiger tiger) {

        this.tiger = tiger;

    }

    public Monkey getMonkey() {

        return monkey;

    }

    public void setMonkey(Monkey monkey) {

        this.monkey = monkey;

    }

   

    public String toString(){

        return tiger + " " + monkey;

    }

   

}

 

spring的配置文件这么写:

 

<?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:p="http://www.springframework.org/schema/p"

    xmlns:context="http://www.springframework.org/schema/context"

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

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

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

    http://www.springframework.org/schema/context/spring-context-3.0.xsd

    ">

   

     <bean id="zoo" class="com.spring.model.Zoo" >

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

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

    </bean>

   

    <bean id="tiger" class="com.spring.model.Tiger" />

    <bean id="monkey" class="com.spring.model.Monkey" />

 

</beans>

 

测试方法:

 

public class TestAnnotation {

    /**

     * 不使用注解

     */

    @Test

    public void test(){

        //读取配置文件

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

        Zoo zoo=(Zoo) ctx.getBean("zoo");

        System.out.println(zoo.toString());

    }

}

 

1.1.2            采用spring注解自动装备bean

采用注解之后,不需要再配置文件中配置类之间的依赖关系,也无需定义set和get接口,只需将类定义为bean,让spring能够识别bean,然后在需要注入的引用前面加上@Autowired注解,IOC就会自动的按照类型匹配的方式查找bean,将bean对象注入到引用中。

@Autowired

@Autowired顾名思义,就是自动装配,其作用是为了消除代码Java代码里面的getter/setter与bean属性中的property。当然,getter看个人需求,如果私有属性需要对外提供的话,应当予以保留。

@Autowired默认按类型匹配的方式,在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入@Autowired标注的变量中。

因此,引入@Autowired注解,先看一下spring配置文件怎么写:

 

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

 2 <beans

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

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

 5     xmlns:p="http://www.springframework.org/schema/p"

 6     xmlns:context="http://www.springframework.org/schema/context"

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

 8     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

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

10     http://www.springframework.org/schema/context/spring-context-3.0.xsd

11     ">

12    

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

14    

15     <bean id="zoo" class="com.spring.model.Zoo" />

16     <bean id="tiger" class="com.spring.model.Tiger" />

17     <bean id="monkey" class="com.spring.model.Monkey" />

18

19 </beans>

 

注意第13行,使用必须告诉spring一下我要使用注解了,告诉的方式有很多,<context:component-scan base-package="xxx" />是一种最简单的,spring会自动扫描xxx路径下的注解。

看到第15行,原来zoo里面应当注入两个属性tiger、monkey,现在不需要注入了。再看下,Zoo.java也很方便,把getter/setter都可以去掉:

 

package com.spring.model;

 

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

 

public class Zoo {

   

    @Autowired

    private Tiger tiger;//自动注入对象

   

    @Autowired

    private Monkey monkey;// //自动注入对象

   

    public String toString(){

        return tiger + " " + monkey;

    }

   

}

 

这里@Autowired注解的意思就是,当Spring发现@Autowired注解时,将自动在代码上下文中找到和其匹配(默认是类型匹配)的Bean,并自动注入到相应的地方去。

如果将16.17行去掉,ioc就无法找到tiger和monkey的bean。@Autowired注解要去寻找的是一个Bean,Tiger和Monkey的Bean定义都给去掉了,自然就不是一个Bean了,Spring容器找不到也很好理解。那么,如果属性找不到我不想让Spring容器抛出异常,而就是显示null,可以吗?可以的,其实异常信息里面也给出了提示了,就是将@Autowired注解的required属性设置为false即可:

 

package com.spring.model;

 

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

 

public class Zoo {

   

    @Autowired(required=false)

    private Tiger tiger;

   

    @Autowired(required=false)

    private Monkey monkey;

   

    public String toString(){

        return tiger + " " + monkey;

    }

   

}

 

此时,找不到tiger、monkey两个属性,Spring容器不再抛出异常而是认为这两个属性为null。

1.1.3            Qualifier(指定注入Bean的名称)

定义一个接口,有两个类实现了它,在使用接口引用自动注入时,因为有两个实现类,所以无法知道注入哪个类,所以要用Qualifier指定实现类的名称。那么如果容器中有一个以上匹配的Bean,则可以通过Qualifier注解限定Bean的名称,看下面的例子:

定义一个Car接口:

package com.spring.service;

 

public interface ICar {

   

    public String getCarName();

}

两个实现类BMWCar和BenzCar:

 

package com.spring.service.impl;

 

import com.spring.service.ICar;

 

public class BMWCar implements ICar{

   

    public String getCarName(){

        return "BMW car";

    }

}

 

 

package com.spring.service.impl;

 

import com.spring.service.ICar;

 

public class BenzCar implements ICar{

   

    public String getCarName(){

        return "Benz car";

    }

}

 

再写一个CarFactory,引用car(这里先不用@Qualifier注解):

 

package com.spring.model;

 

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

 

import com.spring.service.ICar;

 

public class CarFactory {

   

    @Autowired

    private ICar car;

   

    public String toString(){

        return car.getCarName();

    }

   

}

 

配置文件:

 

<?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:p="http://www.springframework.org/schema/p"

    xmlns:context="http://www.springframework.org/schema/context"

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

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

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

    http://www.springframework.org/schema/context/spring-context-3.0.xsd

    ">

   

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

   

    <!-- Autowired注解配合Qualifier注解 -->

    <bean id="carFactory" class="com.spring.model.CarFactory" />

    <bean id="bmwCar" class="com.spring.service.impl.BMWCar" />

    <bean id="benz" class="com.spring.service.impl.BenzCar" />

   

</beans>

 

测试方法:

 

/**

 * Autowired注解配合Qualifier注解

 */

@Test

public void test1(){

    //读取配置文件

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

    CarFactory carFactory=(CarFactory) ctx.getBean("carFactory");

    System.out.println(carFactory.toString());

}

 

运行一下,不用说,一定是报错的,Car接口有两个实现类,Spring并不知道应当引用哪个实现类。所以要用Qualifier指定。

package com.spring.model;

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

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

import com.spring.service.ICar;

 

public class CarFactory {

   

    @Autowired

    @Qualifier("bmwCar")

    private ICar car;

   

    public String toString(){

        return car.getCarName();

    }

   

}

1.1.4            @Resource与@Autowired的异同

@Resource注解与@Autowired注解作用非常相似,这个就简单说了,看例子:

 

package com.spring.model;

 

import javax.annotation.Resource;

 

public class Zoo1 {

   

    @Resource(name="tiger")

    private Tiger tiger;

   

    @Resource(type=Monkey.class)

    private Monkey monkey;

   

    public String toString(){

        return tiger + " " + monkey;

    }

}

 

这是详细一些的用法,说一下@Resource的装配顺序:
(1)、@Resource后面没有任何内容,默认通过name属性去匹配bean,找不到再按type去匹配
(2)、指定了name或者type则根据指定的类型去匹配bean
(3)、指定了name和type则根据指定的name和type去匹配bean,任何一个不匹配都将报错然后,区分一下@Autowired和@Resource两个注解的区别:
(1)、@Autowired默认按照byType方式进行bean匹配,@Resource默认按照byName方式进行bean匹配
(2)、@Autowired是Spring的注解,@Resource是J2EE的注解,这个看一下导入注解的时候这两个注解的包名就一清二楚了
Spring属于第三方的,J2EE是Java自己的东西,因此,建议使用@Resource注解,以减少代码和Spring之间的耦合。

1.1.5            @Service注解申明类为bean

上面这个例子, spring的配置文件里面还有15行~17行申明三个类为bean,如果直接在类的定义前面使用注解@service,ioc就会将该类标记为bean。还可以使用下一步的简化是把这三个bean也给去掉,使得spring配置文件里面只有一个自动扫描的标签,增强Java代码的内聚性并进一步减少配置文件。

要继续简化,可以使用@Service。先看一下配置文件,当然是全部删除了:

 

<?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:p="http://www.springframework.org/schema/p"

    xmlns:context="http://www.springframework.org/schema/context"

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

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

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

    http://www.springframework.org/schema/context/spring-context-3.0.xsd

    ">

   

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

   

</beans>

 

然后在类的定义前面加上注解@Service

 

package com.spring.model;

 

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

import org.springframework.stereotype.Service;

 

@Service//申明为bean,默认标识为小写的zoo

public class Zoo {

   

    @Autowired

    private Tiger tiger;

   

    @Autowired

    private Monkey monkey;

   

    public String toString(){

        return tiger + " " + monkey;

    }

   

}

 

默认是在Spring容器中Zoo.java存在的形式就是"zoo",即可以通过ApplicationContext的getBean("zoo")方法来得到Zoo.java。@Service注解,其实做了两件事情:
(1)、声明Zoo.java是一个bean,这点很重要,因为Zoo.java是一个bean,其他的类才可以使用@Autowired将Zoo作为一个成员变量自动注入。
(2)、Zoo.java在bean中的id是"zoo",即类名且首字母小写。

如果,我不想用这种形式怎么办,就想让Zoo.java在Spring容器中的名字叫做"Zoo",可以的:

 

package com.spring.model;

 

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

import org.springframework.context.annotation.Scope;

import org.springframework.stereotype.Service;

 

@Service("Zoo")//申明bean的标识为指定的名称Zoo

@Scope("prototype")

public class Zoo {

   

    @Autowired

    private Tiger tiger;

   

    @Autowired

    private Monkey monkey;

   

    public String toString(){

        return tiger + " " + monkey;

    }

   

}

 

这样,就可以通过ApplicationContext的getBean("Zoo")方法来得到Zoo.java了。

这里我还多加了一个@Scope注解,应该很好理解。因为Spring默认产生的bean是单例的,假如我不想使用单例怎么办,xml文件里面可以在bean里面配置scope属性。注解也是一样,配置@Scope即可,默认是"singleton"即单例,"prototype"表示原型即每次都会new一个新的出来。

原文地址:https://www.cnblogs.com/bclshuai/p/10298727.html