zoukankan      html  css  js  c++  java
  • spring bean的介绍以及xml和注解的配置方法

     

    5.Bean

    下边我们来了解一下Bean的:
    Bean的作用域
    Bean的生命周期
    Bean的自动装配
    Resources和ResourceLoader
     

    5.1Bean容器的初始化

      Bean容器的初始化
      两个基础包:
        org.springframework.beans
        org.springframework.context
        BeanFactory提供配置结构和基本功能,加载并初始化Bean
        ApplicationContext保存了Bean对象并在spring中被广泛使用

      集中常用的使用场景:

      常用的文件初始化方式:

      FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("F:/workspace/appcontext.xml");
      ApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap1/coll.xml");
      BeanFactory factory = new ClassPathXmlApplicationContext("com/xxxspring/chap1/ioc.xml");

      1.在webapp中的我们一般配置到web.xml文件中

    1     <!-- 配置contextConfigLocation指定spring将要使用的配置文件 -->
    2     <context-param>
    3         <param-name>contextConfigLocation</param-name>
    4         <param-value>classpath:action.xml,classpath:dao.xml,classpath:service.xml</param-value>
    5     </context-param>
    6     <!--  配置listner让spring读取配置文件-->
    7     <listener>
    8         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    9     </listener>

      2.load-on-startup标签指定启动顺序,1为指在启动服务器的时候初始化容器

     1 <listener>
     2     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
     3 </listener>
     4  
     5     <servlet>
     6         <servlet-name>remoting</servlet-name>
     7         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     8         <init-param>
     9             <param-name>contextConfigLocation</param-name>
    10             <param-value>classpath:spring-remoting-servlet.xml</param-value>
    11         </init-param>          
    12         <load-on-startup>1</load-on-startup>
    13     </servlet>

    3Bean的两种注入方式

      a.设置值注入

      b.构造注入

      设置值注入案例:

      基本类型的注入: 通过<property name="属性名", value="属性值/">为对应类对象初始化的值,这种方式必须在类中为对应的属性提供getxxx,setxx方法

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4   xsi:schemaLocation="http://www.springframework.org/schema/beans
     5   http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
     6     <bean name="user,user2" class="com.xxx.spring.ioc.bean.User">
     7         <property name="id" value="1"/>
     8         <property name="name" value="tom"/>
     9         <property name="age" value="20"/>
    10         <property name="gender" value="male"/>
    11     </bean>    
    12 </beans>

      引用类型的注入:<property name="属性名" ref="引用的bean"></property>,被引入的bean和引入处可以不在同一个xml文件中,因为所有bean都会被容器初始化并保存到容器中

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4 xsi:schemaLocation="http://www.springframework.org/schema/beans
     5 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
     6     <bean name="memberService" class="com.xxx.run.service.impl.IMemberServiceImpl">
     7         <property name="memberDao" ref="memberDao"></property>
     8     </bean>
     9     <bean name="memberDao" class="com.xxx.run.dao.impl.IMemberDaoImpl"></bean>
    10 </beans>

      构造注入

      顾名思义,使用构造器对对象的初始化注入对应的值,实现方式有如下3种  

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4 xsi:schemaLocation="http://www.springframework.org/schema/beans
     5 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
     6     <bean name="teacher" class="com.xxx.spring.ioc.bean.Teacher">
     7         <!--  1.按照属性名赋值 ,调用有参数的构造器,顺序是参数顺序-->
     8         <constructor-arg name="id" value="1"/> <!-- person(int id,String name, String gender) -->
     9         <constructor-arg name="name" value="tom"/>
    10         <constructor-arg name="gender" value="male"/>
    11         <!-- 2.index从0开始,按照属性在构造器中出现的顺序赋值 索引值是构造器中的属性顺序 -->
    12    <!-- <constructor-arg index="0" value="2"/>
    13         <constructor-arg index="1" value="jack"/>
    14         <constructor-arg index="2" value="male"/> -->
    15         <!-- 3.按照类型进行赋值,如果出现相同的类型,按照属性在构造器中出现的顺序进行复制 -->
    16     <!--<constructor-arg type="int" value="3"/>
    17         <constructor-arg type="String" value="rose"/>
    18         <constructor-arg type="String" value="female"/> -->
    19     </bean>
    20 </beans>

      Teacher.java  

     1 public class Teacher implements Serializable{
     2     private static final long serialVersionUID = 1L;
     3     private int id;
     4     private String name;
     5     private String gender;
     6  
     7     public Teacher(int id, String name, String gender) {
     8         super();
     9         this.id = id;
    10         this.name = name;
    11         this.gender = gender;
    12     }
    13  
    14     @Override
    15     public String toString() {
    16         return "Teacher [id=" + id + ", name=" + name + ", gender=" + gender
    17                 + "]";
    18     }
    19 }

      测试

    1   @Test
    2     public void test3() throws Exception {
    3         ApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap1/constructor.xml");
    4         Teacher teacher = (Teacher) ac.getBean("teacher");
    5         System.out.println(teacher);//Teacher [id=1, name=tom, gender=male]
    6     }

    5.2Bean的生命周期

      Spring中Bean的声明周期的创建和初始化都是由Spring管理创建的,如下Life实现BeanNameAware,BeanFacotryAware,可以获取到一些对应的资源
     1 import org.springframework.beans.BeansException;
     2 import org.springframework.beans.factory.BeanFactory;
     3 import org.springframework.beans.factory.BeanFactoryAware;
     4 import org.springframework.beans.factory.BeanNameAware;
     5  
     6 public class Life implements BeanNameAware,BeanFactoryAware{
     7     private String name;
     8     
     9     public Life(){//一加载就会调到用
    10         System.out.println("调用无参构造器");
    11     }
    12  
    13     public String getName() {
    14         return name;
    15     }
    16  
    17     public void setName(String name) {
    18         System.out.println("调用setName方法");
    19         this.name = name;
    20     }
    21     
    22     public void myInit() {
    23         System.out.println("调用myInit方法");
    24     }
    25     
    26     public void myDestory(){
    27         System.out.println("调用myDestory方法");
    28     }
    29  
    30     @Override
    31     public void setBeanFactory(BeanFactory arg0) throws BeansException {
    32         System.out.println("调用setBeanFactory方法");
    33         
    34     }
    35  
    36     @Override
    37     public void setBeanName(String arg0) {
    38         System.out.println("调用setBeanName方法");
    39     }
    40 }
      life.xml文件配置
      init-method指明bean初始化需要执行的方法,
      destory-method指明bean销毁需要执行的方法
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4        xmlns:u="http://www.springframework.org/schema/util"
     5        xsi:schemaLocation="http://www.springframework.org/schema/beans
     6            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
     7            http://www.springframework.org/schema/util
     8            http://www.springframework.org/schema/util/spring-util-3.2.xsd">
     9            <!-- 调用set方法赋值后会调用myInit方法    myDestory方法最后调用-->
    10     <bean name="life" class="com.xxx.spring.ioc.bean.Life" init-method="myInit" destroy-method="myDestory">
    11         <property name="name" value="tom"></property>
    12     </bean>
    13 </beans>
      测试:
      注意:在xml文件中指明destory-method需要执行的方法后,bean生命周期并不会自动去掉用myDestory方法,需要ac.detstory(),才会调用
    1     @Test
    2     public void life(){//springBean的生命周期    
    3         ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap2/life.xml");
    4         Life life = ac.getBean("life",Life.class);
    5         System.out.println(life);
    6         ac.destroy();
    7     }
      结果:
        调用无参构造器
        调用setName方法
        调用setBeanName方法
        调用setBeanFactory方法
        调用myInit方法
        com.briup.spring.ioc.bean.Life@4f0b5b
        调用myDestory方法
        AfterClass 标注的方法 会最后执行

    5.3Bean作用域

      介绍两个常用的
      scope="prototype"原型模式,该模式下每次都会创建一个新的对象
      <bean id="user" class="com.briup.spring.ioc.bean.User" scope="prototype"></bean>
      scope = "singleton" 单例模式,该模式下容器中只会存在一个这样的对象
      <bean id="user" class="com.briup.spring.ioc.bean.User" scope="singleton"></bean>
     
      其他的参考:
      http://blog.csdn.net/fengruifang/article/details/6522262

    5.4Bean的自动装配

      上边的Bean不管通过设置值注入,或通过构造器注入,我们都显示的声明了需要注入的值
      还有一种方式也比较常用,对应引用类型的注入我们可以通过autowire自动注入
      autowire有三种方式
        1.constructor
          如下边我们不显示声明address属性的值,autowire=“constructor”,即初Student中提供了
            public Student(Address address) {
              this.address = address;
            }
          构造器,初始化Bean的时候,会去容器中查找Address.class对象是否存在,如果存在,则注入到该bean对象中,如不存在address为null
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4 xsi:schemaLocation="http://www.springframework.org/schema/beans
     5 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
     6     <bean name="student" class="com.xxx.spring.ioc.bean.Student" autowire="constructor"><!-- byName byType  constructor(一定要提供一个单参数的构造器)-->
     7         <property name="name" value="tom"/>
     8         <property name="age" value="20"/>
     9     <!--     <property name="address" ref="address"/> -->
    10     </bean>
    11     <bean name="address" class="com.briup.spring.ioc.bean.Address">
    12         <property name="country" value="中国"></property>
    13         <property name="province" value="江苏"></property>
    14         <property name="city" value="苏州"></property>
    15     </bean>
    16 </beans>
        2.byName
          同理,autowire=“byName”,初始化bean的时候,会去容器中查找名字为address的bean注入到student对象中,Student需要提供对应的getxx,setxx
        3.byType
          autowire=“byType”,初始化bean的时候,会取容器中通过类型查找是否有Class为Address.class类型的对象,查找到则注入到student对象中需要提供getxx,setxx 

    5.3 Aware

      spring中提供了许多已Aware结尾的类,这些类可以获取容器中的一些资源
      比如ApplicationContextAware,可以获取applicationCcontext中的内容
      BeanNameAware可以获取到Bean的beanName
      aware.xml
    1 <?xml version="1.0" encoding="UTF-8"?>
    2 <beans xmlns="http://www.springframework.org/schema/beans"
    3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4 xsi:schemaLocation="http://www.springframework.org/schema/beans
    5 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
    6     <bean name="applicationAawareTest" class="com.xxx.spring.aop.bean.AwareTest"></bean>
    7 </beans>
      AwareTest.java
     1 import org.springframework.beans.BeansException;
     2 import org.springframework.beans.factory.BeanNameAware;
     3 import org.springframework.context.ApplicationContext;
     4 import org.springframework.context.ApplicationContextAware;
     5  
     6 public class AwareTest implements ApplicationContextAware,BeanNameAware{
     7  
     8     @Override
     9     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    10         System.out.println(applicationContext.getBean(AwareTest.class));
    11     }
    12  
    13     @Override
    14     public void setBeanName(String beanName) {
    15         System.out.println(beanName);
    16     }
    17  
    18
      测试:
    1     @Test
    2     public void AwareTest(){
    3         ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap1/aware.xml");
    4         AwareTest awareTest = ac.getBean("applicationAawareTest",AwareTest.class);
    5         System.out.println(awareTest);
    6     }
      结果:
        applicationAawareTest
        com.xxx.spring.aop.bean.AwareTest@1d8fe20
        com.xxx.spring.aop.bean.AwareTest@1d8fe20

    5.4Resource统一文件资源接口

      Resources针对文件的统一接口,用于操作本地资源或网络资源,或其他
        -UrlResource:URL对应的资源,根据一个URL地址既可以构建
        -ClassPathResource:获取类路径下的资源文件
        -FileSystemResource:获取文件系统中的资源文件
        -ServletContextResource:ServletContext封装资源,用于访问ServletContext环境下的资源
        -InputStreamResource:针对输入流封装的资源
        -ByteArrayResource:针对字节数组封装的资源

       ResourceLoader
        -所用的application context 实现了ResourceLoader接口

        spring中ResourceLoader定义如下:

    1 public interface ResourceLoader{
    2     Resource getResource(String location);
    3 }

         getResource中location的写法有如下几种
      prefix前缀 案例     说明
      classpath: classpath:com/briup/spring/chap2/life.xml 从classpath中加载
      file: file:/data/life.xml用URL从文件系统中加载
      http: http://myserver/logoo.png通过URL从网络加载
      (none) /spring/chap2/life.xml 这种相对路径的写法依赖于ApplicationContext

      spring中的使用

        Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
        Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
        Resource template = ctx.getResource("file:some/resource/path/myTemplate.txt");

      案例:

      resources.xml

    1 <?xml version="1.0" encoding="UTF-8"?>
    2 <beans xmlns="http://www.springframework.org/schema/beans"
    3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4 xsi:schemaLocation="http://www.springframework.org/schema/beans
    5 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
    6     <bean name="resourcetest" class="com.briup.spring.aop.bean.ResourceTest"/>
    7 </beans>

    ResourceTest.java

    由于spring中所有的applicationcontext实现了ContextLoader接口, 所以我们实现applicationContext即有了ResourceLoader的能力

    下边:classpath:在eclipse中会加载src下的config.txt文件

     1 import java.io.IOException;
     2  
     3 import org.springframework.beans.BeansException;
     4 import org.springframework.context.ApplicationContext;
     5 import org.springframework.context.ApplicationContextAware;
     6 import org.springframework.core.io.Resource;
     7  
     8  
     9 //所有的ApplicationContext实现了ResourceLoader接口
    10 public class ResourceTest implements ApplicationContextAware{
    11     
    12     private ApplicationContext ApplicationContext;
    13  
    14     @Override
    15     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    16         this.ApplicationContext = applicationContext;
    17     }
    18     
    19     public void resource() throws IOException{
    20         //Resource resource = ApplicationContext.getResource("config.txt");//默认为classpath
    21         //Resource resource = ApplicationContext.getResource("classpath:config.txt");
    22         //Resource resource = ApplicationContext.getResource("file:D:\workspace\xnxy_spring\src\config.txt");
    23         Resource resource = ApplicationContext.getResource("url:http://repo.springsource.org/libs-release-local/org/springframework/spring/3.2.4.RELEASE/spring-framework-3.2.4.RELEASE-dist.zip");
    24         System.out.println(resource.getFilename());//获取文件名
    25         System.out.println(resource.contentLength()); //获取文件长度
    26         System.out.println(resource.getInputStream());//获取输入流
    27     }
    28 }

      测试:

     1   @Test
     2     public void ResourceTest(){
     3         ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("com/briup/spring/chap1/resources.xml");
     4         ResourceTest resourceTest = ac.getBean("resourcetest",ResourceTest.class);
     5         try {
     6             resourceTest.resource();
     7         } catch (IOException e) {
     8             e.printStackTrace();
     9         }
    10     }

    6.Bean容器的注解实现

      下边我们主要了解如下使用:
        Classpath扫描与组件管理
        类的自动检测与注册Bean
        <context:annotation-config/>
        @Component, @Repository, @Service, @Constroller
        @Required
        @Autowired
        @Qualifier
        @Resource

    6.1classpath扫描与组件管理

    从Spring3.0开始,Spring JavaConfig项目提供了很多特性,包括使用java而不是XML定义Bean,比如
    @Configuration, @Bean, @Import, @DependsOn
    @Component是Spring中的一个通用注解,可以用于任何Bean,相当于注解的超类,如果不知道位于那个层,一般使用该注解
    @Repository, @Service, @Controller是更具有针对性的注解
    - @Repository,通常用于注解DAO,即持久层的注解
    - @Service,通常用于追注解Service类,即服务层
    - @Controller通常用于注解Controller,即控制层(MVC)

    6.2类的自动检测与注册Bean

    我们再xml下配置如下标签,可以指定某个包路劲,扫描该包以及子包下,使用了spring注解的bean注册哦容器中,basp-package指向扫描那个包下的注解类
    1 <context:component-scan base-package="spring.aop.bean.annotation"></context:component-scan>
    我们还可以使用如下标签,context:annotation-config,不过context:component-scan包含context:annotation-config的全部功能,通常使用前者后,不再使用后者,context:component-scan一般用于基于类的注解(包括成员变量或成员方法的注解),但是context:annotation-config只能在完成bean注册后,去处理bean类中的成员变量或成员方法的注解.
     
    过滤注解:
     1     <!--默认情况下,spring中自动发现并被注册bean的条件是:
     2         使用@Component, @Repository, @Service, @Constroller其中之一的注解
     3         或者使用基于@Component的自定义注解
     4      
     5         可以通过过滤器修改上边的行为,如下边的例子XML配置忽略所有@Repository注解并用“stub”代替
     6         -->
     7     
     8 
     9        <context:component-scan base-package="spring.aop.bean.annotation">
    10            <!-- 通过include-filter包含注解,exclude-filter排除注解 -->
    11            <context:include-filter type="regex" expression=".*Stub.*Repository"/>
    12            <!-- 排除@Repository注解 -->
    13            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
    14        </context:component-scan>

    6.3使用注解管理bean

    这里我们先使用 @Bean @Service @Repository @Componet
    扫描过程中组件自动检测,那么Bean名称是有BeanNameGenerator生成的( @Component, @Repository, @Service, @Controller
    都会有个name属性用于显示设置BeanName)
     
    Service

    //显示设置beanName,相当于在xml配置bean的是id的值
    @Service("myMoveLister")
    public class simpleLlister{
    //..

    }

    Dao

    //设置beanName默认使用类名,首字母小写作为beanName
    @Repository
    public class MovieFinderImpl implements MovieFinder{

    }

    6.3.1 作用域scope

    作用域的注解Scope
    通常情况下自动查找的Spring组件,其Scope是singleton,其Spring2.5提供了Scope的注解 @Scope

    @Scope("prototype")  //括号中指定Scope的范围,默认
    @Repository
    public class MovieFinderImpl implements MovieFinder{


    }


    也可以自定义scope策略,实现ScopeMetadataResolver接口并提供一无参数的构造器

     <context:component-scan base-package="spring.aop.bean.MyScopeResolver"></context:component-scan>

    6.3.2注解的具体案例使用

    //由于不知道其作用于DAO或Service所以使用通用注解,如果知道具体作用在那层,我们一班使用更具体注解方式如@Service,@Repository等

    1 //@Component -->默认使用类名小写作为bean的name
    2 @Scope("prototype") //括号中为Scope的范围,这里设置为原型模式
    3 @Component("beanAnnotation")
    4 public class BeanAnnotation {
    5     
    6     public void say(String arg){
    7         System.out.println("BeanAnnotation: "+arg);
    8     }
    9 }

    测试:

     1 @Test
     2 public void testAnnotation(){
     3     ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap4/annotation.xml");
     4     //@Component没有value值的话,默认使用类名首字母小写作为bean的id,指定value以value值为准作为id
     5     BeanAnnotation beanAnnotation1  = ac.getBean("beanAnnotation",BeanAnnotation.class);
     6     BeanAnnotation beanAnnotation2  = ac.getBean("beanAnnotation",BeanAnnotation.class);
     7     System.out.println(beanAnnotation1);
     8     System.out.println(beanAnnotation2);
     9     //结果
    10     //com.xxx.spring.aop.bean.annotation.BeanAnnotation@1598d5f
    11     //com.xxx.spring.aop.bean.annotation.BeanAnnotation@505fd8
    12 }
    6.3.3一个不常用的注解@Required
    @Required注解使用于注解bean属性的setter方法
    这个注解仅仅标识,受影响的bean属性必须在配置时被填充,通过bean定义或通过自动装配一个明确的属性值
    这个注解并不是很常用,更常用的是@Autowired
    pulic class simpleMovieLister{
      private MoiveFinder movieFinder;
      @Required
      public void setMovieFinder(MovieFinder movieFinder){
        this.movieFinder  = movieFinder;
      }
      //..
    }
    6.3.4@Autowired

    这个注解相当于我们之前在xml文件中配置的autowire="constructor/byName/byType",只不过我们这里使用@Autowired方式注解方式,且默认是通过类型判断,意思就是不使用byName,和construtor。通过@Autowired注解,spring会自动去容器中查找对应的类型,注入到该属性中,且bean类中,使用@Autowired注解其属性,我们可以不用提供getter,setter方法

    使用@Autowired

    @Autowried对属性进行注解的时候,我们可以省略getter,setter方法,通过对应的bean的类型,对属性值注入
    @Autowried对seter方法进行注解的时候,可以注入对应的值
    @Autowried对构造器进行注解的时候,可以通过类型找到对应的bean注入
    @Autowried可以将 @Autowried为”传统“的setter方法代替 @Required
    @Autowried自动注入,会去容器中按照类型查找对应的bean注入

    案例:

    setter中使用

     1 pulic class simpleMovieLister{
     2     
     3         private MoiveFinder movieFinder;
     4  
     5         @Autowried
     6         public void setMovieFinder(MovieFinder movieFinder){
     7             this.movieFinder  = movieFinder;
     8         }
     9         //..
    10 }

    属性和构造器中使用

     1 pulic class MovieRreCommender{
     2     
     3         成员变量中
     4         @Autowried
     5         private MovieCatalog movieCatalog;
     6  
     7         private CustomerPreferenceDao customerPreferenceDao;
     8  
     9         //构造器中
    10         @Autowried
    11         public MovieRreCommender(CustomerPreferenceDao customerPreferenceDao){
    12             this.CustomerPreferenceDao  = CustomerPreferenceDao;
    13         }
    14 }

    上边的seter方式,构造器方式,属性方式,效果都是一样的,使用其中任何一种,都可以实现注入。不过由于,@Autowired是通过类型判断是否注入到使用该注解地方,假如容器中出现两个以上的相同类型的bean实例,就会报错,这时我们就必须指定注入那个id名的bean实例,主要有两种方法解决该问题:

    @Autowired(requried=false), @Qualifie("beanName)指定@Autowired注入那个bean实例

    6.3.5@Autowried(requried=false)

    默认情况下,如果因找不到合适的bean将会导致autowiring失败抛出异常,可以通过下边
    这种方式避免

    pulic class simpleMovieLister{

    private MoiveFinder movieFinder;

    @Autowried(requried=false)//指明该属性不是必须的,找不到的情况下不会抛出异常
    public void setMovieFinder(MovieFinder movieFinder){
    this.movieFinder  = movieFinder;
    }
    //..
    }
    提示:每一类中只能有一个构造器被标记为requried=ture建议将 @Autowired的必要属性时,使用 @Requried注解

    6.3.6@Qualifier--配合 @Autowired
    如果使用 @Autowired自动装配可能存在多个相同类型的bean的时候,可以使用spring的 @Qualifier
    注解缩小注解范围(或指定唯一),也可以用于指定单独的构造参数的方法参数
    可以适用于注解集合类型的变量

    案例:
     1 public class MovieRecommander{
     2     @Autowired
     3     @Qualifier("beanName")
     4     private MovieCatalog movieCatalog;
     5  
     6     private CustomerPreferenceDao customerPreferenceDao;
     7   //@Qualifier也可以实现参数的注入
     8     public void prepare(@Qualifier("beanName")CustomerPreferenceDao customerPreferenceDao){
     9         this.customerPreferenceDao = customerPreferenceDao;
    10     }
    11 }
    上边的案例:假设MovieCatalog在容器中存在多个相同的类型的情况下,可以结合使用 @Qualifier("beanName")
    指定一个bean的id注入到该属性中,可以在方法的参数中使用

     6.3.7@Autowired注解可以方便的注解那些众所周知的解析依赖性接口

    比如说:BeanFacotry,ApplicationContext,Environment,ResourceLoader,ApplicaiontEventPublisher, MessageSource等

    1     pulic class simpleMovieLister{
    2     
    3         @Autowired
    4         private AplicationContext context;
    5  
    6         public simpleMovieLister(){}
    7     
    8     }

    上边的案例使用autowired注解ApplicationContext,这样我们就可以活ApplicatioinContext容器总的bean对象

    6.3.8@Autowired将容器中相关类型的bean注入到一个集合或数组中
    使用@Autowired注解,可以将容器中的bean实例注入到集合或数组中,如果是注入到数组中通过配合@Order("排序值"),可以实现对数组或list的排序,也只能对数组或list排序,其他的如Map是不需要排序的。
     
    案例:接口BeanInfterface
    1 public interface BeanInterface {
    2  
    3  
    4 }
    实现类1:
    1 @Order(1)
    2 @Component
    3 public class BeanImplOne implements BeanInterface {
    4  
    5 }
    实现类2:
    1 @Order(2)  //Order排序注解只对list,或数组集合有效括号里边是排序顺序
    2 @Component
    3 public class BeanImplTwo implements BeanInterface {
    4  
    5 }
    调用类:
     1 import java.util.List;
     2 import java.util.Map;
     3 import java.util.Map.Entry;
     4 import java.util.Set;
     5 import org.springframework.beans.factory.annotation.Autowired;
     6 import org.springframework.stereotype.Component;
     7  
     8 @Component
     9 public class BeanInvoker {
    10     
    11     @Autowired //该注解会将所有的BeanInterface类型的bean注入到该list中
    12     //如果bean有 @Order注解可以实现排序
    13     private List<BeanInterface> list;
    14     
    15     //该注解会将所有的BeanInterface类型的bean注入到该map中,key值为bean的名字
    16     //是String类型,map类型无排序可言
    17     @Autowired
    18     private Map<String, BeanInterface> map;
    19     
    20     public void print(){
    21         if(list != null && 0 != list.size()){
    22             System.out.println("list...");
    23             for(BeanInterface beanInterface:list){
    24                 System.out.println(beanInterface.getClass().getName());
    25             }
    26         }
    27         if(map != null && 0 != map.size()){
    28             System.out.println("map...");
    29             Set<Entry<String, BeanInterface>> entrySet = map.entrySet();
    30             for(Entry<String, BeanInterface> entry: entrySet){
    31                 System.out.println(entry.getKey()+"--"+entry.getValue().getClass().getName());
    32             }
    33         }
    34     }
    35 }
    测试类:
    1 @Test
    2 public void testAutowired2(){
    3         ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap4/annotation.xml");
    4         BeanInvoker beanInvoker = (BeanInvoker) ac.getBean("beanInvoker");
    5         beanInvoker.print();
    6 }
    结果:
    list...
    com.xxx.spring.aop.bean.annotation.BeanImplOne
    com.xxx.spring.aop.bean.annotation.BeanImplTwo
    map...
    beanImplOne--com.xxx.spring.aop.bean.annotation.BeanImplOne
    beanImplTwo--com.xxx.spring.aop.bean.annotation.BeanImplTwo

    6.4@Bean注解的使用

    @Bean是基于容器的注解,我们可以在使用@Compent注解的地方配合@Bean使用,不过@Bean注解一般不于@Compent注解使用,我们一般使用
    @Bean注解配合@Configuration注解使用,相当于我们再xml配置文件中定义了<bean></bean>
     
    使用:
     1 @Configuration   //相当于配置文件
     2 public class Appconfig{
     3     
     4     @Bean("myservice")//假如bean的name属性没有指定名字的话,注入的是id为方法名的bean,一般我们指定name属性不容易出错
     5     public Myservice myservice(){
     6         return new MyServiceImpl();
     7     }
     8     /*
     9         对比基于XML文件中的配置效果类似
    10         <bean id="myservice" class="com.xxx.service.MyserviceImpl"></bean>
    11     */
    12 }
    @Bean中的其他他几个属性
     
    之前我们再配置文件中使用过如下的配置,指定bean的初始化调时会执行的方法,和销毁会执行的方法
    1 <bean name="life" class="com.briup.spring.ioc.bean.Life" init-method="myInit" destroy-method="myDestory">
    2         <property name="name" value="tom"></property>
    3 </bean>
    我们使@Bean配置也可以实现上边这种效果
     1 public class Foo{
     2     public void init(){
     3     
     4     }
     5 }
     6  
     7 public class Bar{
     8     public void cleanup(){
     9     
    10     }
    11 }
     1 @Configuration 
     2 public class Appconfig{
     3     
     4     @Bean(name="life")  //定义bean的name
     5     public Life life(){
     6         return new Life();
     7     }
     8  
     9     @Bean(initMethod="init") //在初始化Foo的时候,会调用Foo.java中的init方法
    10     public Foo foo(){
    11         return new Foo();
    12     }    
    13     
    14     @Bean(destoryMethod=“cleanup”) //在销毁Bar的时候会调用Bar.java中的cleanup中的方法
    15     public Bar bar(){
    16         return new Bar();
    17     }
    18 }

    6.5使用注解模拟连接数据库

    db.properties内容如下:
    jdbc.driver=oracle.jdbc.driver.OracleDriver
    jdbc.url=jdbc:oracle:thin:@localhost:1521:XE
    jdbc.username=caojx
    jdbc.password=caojx
     
    config.xml配置如下
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"  
     3  xmlns:context="http://www.springframework.org/schema/context"  
     4  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
     5  xsi:schemaLocation="http://www.springframework.org/schema/beans  
     6       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
     7       http://www.springframework.org/schema/context  
     8       http://www.springframework.org/schema/context/spring-context.xsd" >
     9        <!-- 加载db.properties文件 -->
    10        <context:property-placeholder location="classpath:db.properties"/>
    11        <!--context:component-scan包含context:annotation-config的全部功能,通常使用前者后,不再使用后者
    12        <context:component-scan base-package="com.briup.spring.aop.bean.annotation"></context:component-scan>
    13  
    14 </beans>
     
    使用如下类,打印出配置文件中db.properties中的信息
    1 public class MyDriverManager {
    2     
    3     public MyDriverManager(String url, String userName, String password){
    4         System.out.println("url :"+url);
    5         System.out.println("userName :"+userName);
    6         System.out.println("password :"+password);
    7     }
    8  
    9 }
    读取配置文件中的信息
     1 @Configuration
     2 @ImportResource("classpath:com/xxx/spring/chap4/config.xml")  //指定配置文件的路径
     3 public class MyConnection {
     4     
     5     
     6     @Value("${jdbc.url}")  //基本类型的变量使用@Value注解(括号里边是注入的值)  ,这是使用${是读取配db.properties中的值}
     7     private String url;
     8     
     9     @Value("${jdbc.username}")  //如果db.properties中写法为username默认取的是当前操作系统用户的名称,可以在db.properties定义username的时候使用jdbc.username
    10     private String userName;
    11     
    12     @Value("${jdbc.password}")
    13     private String password;
    14     
    15     @Bean(name="myDriverManager")
    16     
    17     public MyDriverManager MyDriverManager(){
    18         return new MyDriverManager(url,userName,password);
    19     }
    20  
    21 }
     
    测试:
    ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap4/annotation.xml");
    System.out.println(ac.getBean("myDriverManager"));
    结果:
    url :jdbc:oracle:thin:@localhost:1521:XE
    userName :caojx
    password :caojx
    com.briup.spring.aop.bean.annotation.MyDriverManager@152b54b

    同时:@Bean注解也可以配置@Scope使用

     1 @Bean(name="myDriverManager")
     2 @Scope("prototype")
     3 public MyDriverManager MyDriverManager(){
     4     return new MyDriverManager(url,userName,password);
     5 }
     6  
     7 @Bean(name="myDriverManager")
     8 @Scope("singleton")
     9 public MyDriverManager MyDriverManager(){
    10     return new MyDriverManager(url,userName,password);
    11 }

    提示:spring配置数据库连接,或事务管理这一块,将会专门使用一篇来说明。


    6.6Spring对JSR的注解支持

    JSR常见的注解有如下

    @Resource等效于@Autowired与@Inject
    @PostConstrct  初始化回掉
    @PreDetory   销毁回调用
    @Inject 等效于 @Autowired
    @Named 与 @Compenet等效

    6.6.1@Resource
    @Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,
    而@Resource默认按 byName自动注入罢了。
    @Resource有两个属性是比较重要的,分是name和type,
    Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。
    所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
      @Resource装配顺序
      1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
      2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
      3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
      4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配; 
           5. 如果 @Resource用于方法中,默认使用方法名作为beanName,指定名字则使用名字

    案例:

    DAO

     1 import org.springframework.stereotype.Repository;
     2  
     3 @Repository
     4 public class JsrDAO {
     5     
     6     public void save(){
     7         System.out.println("JsrDao invoker");
     8     }
     9  
    10 }

    Service

     1 import javax.annotation.PostConstruct;
     2 import javax.annotation.PreDestroy;
     3 import javax.annotation.Resource;
     4  
     5 import org.springframework.stereotype.Service;
     6  
     7 import com.briup.spring.aop.bean.annotation.dao.JsrDAO;
     8  
     9 @Service
    10 public class JsrService {
    11     
    12     @Resource
    13     private JsrDAO jsrDAO;
    14     
    15     @Resource  //作用与上边一样,二选一都可以
    16     public void setJsrDAO(JsrDAO jsrDAO){
    17         this.jsrDAO = jsrDAO;
    18     }
    19     
    20     public void save(){
    21         jsrDAO.save();
    22     }
    23     
    24     @PostConstruct
    25     public void init(){
    26         System.out.println("jsr Service init");
    27     }
    28     
    29     @PreDestroy
    30     public void destory(){
    31         System.out.println("jsr Service destory");
    32     }
    33     
    34 }

    提示:

    @Resource的处理是由ApplicationContext中的CommonAnnotationBeanPostProecssor发现并处理的
    CommonAnnotationBeanPostProecssor不仅支持 @Resource注解,还支持 @PostConstruct初始回调
    和 @PreDestory销毁回调,前提是CommonAnnotationBeanPostProecssor是在ApplicationContext中注册的

    测试结果:

    @Test
    public void testJsr(){
    ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("com/briup/spring/chap4/annotation.xml");
    System.out.println(ac.getBean("jsrService"));
    ac.destroy();
    }

    结果:

    jsr Service init
    com.briup.spring.aop.bean.annotation.service.JsrService@7dc4cb
    jsr Service destory

    @Resource是一个比比较常用的JSR注解,对于JSR中的其他注解,这里不进行详细的介绍。

  • 相关阅读:
    iOS 简单获取当前地理坐标
    iOS 企业账号申请证书和打包ipa
    iOS 代码片段的添加!
    iOS 扩展类方法之category!
    iOS 数组和字典排序
    iOS 字符串NSString 的一些常用方法
    iOS 一些常见问题
    iOS 数据库sqlite完整增删改查操作
    iOS pch文件的创建
    iOS 通过网络请求获取图片的下载歌曲
  • 原文地址:https://www.cnblogs.com/EmilZs/p/9253218.html
Copyright © 2011-2022 走看看