zoukankan      html  css  js  c++  java
  • 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一个新的出来。

  • 相关阅读:
    android136 360 拖拽
    android134 360 07 归属地查询
    android133 360 06 一键锁频,清楚数据
    转载:必须收藏!50个最流行的免费Kubernetes工具集
    SQL Data Compare 对比 SQLserver数据
    PLSQL 使用ODBC 数据源导入来自SQLSERVER的数据
    PLSQL 使用技巧汇总贴(一个坑)
    简单的数据库备份语句--Oracle+SQLSERVER
    SQLSERVER 导出表数据为insert 语句
    Oracle 使用PLSQL 导出 一个表的insert 语句
  • 原文地址:https://www.cnblogs.com/bclshuai/p/10298727.html
Copyright © 2011-2022 走看看