• Spring学习记录(十一)---使用注解和自动装配


    Spring支持用注解配置Bean,更简便。

     上面的组件,是根据实际情况配的。比如写的一个类,是做业务处理的,那就用注解@Service表示服务层组件,以此类推。将整体分成不同部分。

    要在xml加入context命名空间

    1      <!-- 指定Spring IOC容器扫描的包 -->
    2      <context:component-scan base-package="package com.guigu.spring.beans.annotation"></context:component-scan>

     这样,就表示要自动扫描 基类包的类以及子包中的类。类中有注解,就会被管理

     例子:

     目录结构如下,第一个annotation包为要扫描的包,有下面三个子包:controller、repository、service

    类里面都是一个简单的注解和一个方法:

    1    //TestObject.java
    2 package com.guigu.spring.beans.annotation;
    3 
    4 import org.springframework.stereotype.Component;
    5 
    6 @Component
    7 public class TestObject {
    8     
    9 }
     1    //UserController.java
     2 package com.guigu.spring.beans.annotation.controller;
     3 import org.springframework.stereotype.Controller;
     4 
     5 @Controller
     6 public class UserController {
     7 
     8     public void execute(){
     9         System.out.println("UserController execute...");
    10     }
    11 }
     1      //UserRepository.java
     2 package com.guigu.spring.beans.annotation.repository;
     3 public interface UserRepository {
     4     
     5     void save();
     6 }
     7 
     8     //UserRepositoryImpl.java  继承 UserRepository
     9 package com.guigu.spring.beans.annotation.repository;
    10 import org.springframework.stereotype.Repository;
    11 
    12 @Repository("userRepository");
    13 public class UserRepositoryImpl implements UserRepository {
    14 
    15     @Override
    16     public void save() {
    17         System.out.println("UserRepositoryImpl Save...");
    18     }
    19 
    20 }

     写一个继承,为了说明注解命名可以更改,这里改成了userRepository,否则是默认的userRepositoryImpl,下面讲。

     1      //UserService.java
     2 package com.guigu.spring.beans.annotation.service;
     3 
     4 import org.springframework.stereotype.Service;
     5 
     6 @Service
     7 public class UserService {
     8     
     9     public void add(){
    10         System.out.println("UserService add...");
    11     }
    12 }

     xml最上面已经配置,最后main函数:

     1 package com.guigu.spring.beans.annotation;
     2 
     3 import org.springframework.context.ApplicationContext;
     4 import org.springframework.context.support.ClassPathXmlApplicationContext;
     5 
     6 import com.guigu.spring.beans.annotation.controller.UserController;
     7 import com.guigu.spring.beans.annotation.repository.UserRepository;
     8 import com.guigu.spring.beans.annotation.service.UserService;
     9 
    10 public class Main {
    11 
    12     public static void main(String[] args) {
    13         
    14         ApplicationContext ctx =new ClassPathXmlApplicationContext("beans-annotation.xml");
    15         TestObject to = (TestObject) ctx.getBean("testObject");
    16         System.out.println(to);
    17         UserController userController=(UserController) ctx.getBean("userController");
    18         System.out.println(userController);
    19         UserService userservice=(UserService) ctx.getBean("userservice");
    20         System.out.println(userservice);
    21         UserRepository userRepository=(UserRepository) ctx.getBean("userRepository");  
    22         System.out.println(userRepository);
    23     }
    24 
    25 }

     输出如下:说明对象被创建了

    xml里面没有bean,那main函数怎么获取Bean呢?

    就是用最上面图中蓝色字体。Spring默认命名,名字是它的类名第一个字符小写。如:

    UserService.java类中类名是UserService ,获取bean默认名字就是userService

     也可以更改,如上面的UserRepositoryImpl类,用了@Repository("userRepository"),表示bean名字为userRepository

     在xml中,有一些属性和节点:

     resource-pattern:只扫描特定文件

     context:include-filter: 子节点表示要包含的组件

     context:exclude-filter: 子节点表示要排除在外的组件

    1      <!-- 可以通过resource-pattern指定扫描的资源 -->
    2      <context:component-scan base-package="package com.guigu.spring.beans.annotation"
    3      resource-pattern="repository/*.class">
    4      </context:component-scan>
    5  

     这样,只会扫描repository包下的类,如果main函数中,还要调用其他类,报错。只能调用repository包下的类。

    1     <!-- context:exclude-filter 子节点指定排除哪些指定表达式的组件 -->  
    2      <context:component-scan base-package="package com.guigu.spring.beans.annotation">
    3       <context:exclude-filter type="annotation" expression="package com.guigu.spring.beans.annotation.repository"/>  //type类型后面看
    4      </context:component-scan>
    5  

     这表示不扫描repository子包的文件,若main函数中调用它们,会抛异常

    1      <!-- context:include-filter 子节点指定包含哪些指定表达式的组件, 该子节点需要use-default-filters配合使用 --> 
    2      <context:component-scan base-package="package com.guigu.spring.beans.annotation"
    3      use-default-filters="false">
    4           <context:include-filter type="annotation" 
    5             expression="package com.guigu.spring.beans.annotation"/> 
    6      </context:component-scan>

    注意,use-default-filters默认自动扫描全部,要设置成false不自动扫描,才能实现只扫描部分的功能。

    <context:include-filter>和<context:exclude-filter>子节点支持多种类型的过滤表达式:

    类别 示例 说明
    annotation  com.yl.XxxAnnotation 所有标注了XxxAnnotation的类,该类型采用目标类是否标注了某个注解进行过滤
    assinable  com.yl.XxxService 所有继承或扩展XxxService的类,该类型采用了目标类是否继承或扩展某个特定类进行过滤
    aspectj  com.yl.*Service 所有类名义Service结束的类及继承或扩展它们的类,该类型采用AspectJ表达式进行过滤
    regex  com.yl.anno.* 所有com.yl.anno包下的类。该类型采用正则表达式,根据类的类名进行过滤
    custom  com.yl.XxxTypeFilter  采用XxxTypeFilter通过代码的方式定义过滤原则。该类必须实现org.springframewor

     

    @Autowired自动装配具有兼容类型的单个bean属性。可以对类成员变量方法构造函数进行标注,完成自动装配的工作。 通过 @Autowired的使用来代替set方法。(property 属性通过调用setter方法进行赋值)

    意思就是用它,可以代替xml中的<property name="car" ref="car"> 这样的引用赋值。自动创建bean。

     

    例子:Person类有Car对象,不用 自动装配

     

     1    //Person类
     2 public class Person {    
     3     private Car car;
     4     
     5     public Car getCar() {
     6         return car;
     7     }
     8     public void setCar(Car car) {
     9         this.car = car;
    10     }
    11 }
     1     //Car类
     2 public class Car {
     3     private String brand;
     4     private double price;
     5     
     6     public void setBrand(String brand) {
     7         this.brand = brand;
     8     }
     9     public void setPrice(double price) {
    10         this.price = price;
    11     }
    12 }

     

    xml

    1     <bean id="person" class="com.guigu.spring.bean.Person">     
    2         <property name="car" ref="car"/>     
    3     </bean>     
    4     <bean id="car" class="com.guigu.spring.bean.Car">     
    5         <property name="brand" value=" aodi"/>     
    6         <property name="price" value="200000"/>     
    7     </bean>     

     

    main

    1     ApplicationContext context = new ClassPathXmlApplicationContext("autowired.xml");  
    2     Person person=(Person)ctx.getBean("person");
    3     System.out.println(person);

     

    这是之前的做法。

    @Autowired自动装配的方法

     

    查了一下,在之前版本的Spring中,要使用@Autowired,要在xml写上这一行代码才行

    1 <!-- 该 BeanPostProcessor 将自动对标注 @Autowired 的 Bean 进行注入 -->     
    2   <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

    但现在spring4,<context:component-scan>自动注册AutowiredAnnotationBeanPostProcessor实例,可以使用@Autowired和@Resource、和@Inject注解(一般用@Autowired)

     所以,如果使用了<context:component-scan>,就不用额外注册,不然还是要

    1      //Person类
    2   public class Person {    
    3       //@Aotuwired   //自动根据xml配置实例car对象
    4       private Car car;
    5       
    6  }

     

    1      <bean id="person" class="com.guigu.spring.bean.Person">     
    2     //这里就不需要再写ref="car"  
    3      </bean>     
    4      <bean id="car" class="com.guigu.spring.bean.Car">     
    5          <property name="brand" value=" aodi"/>     
    6          <property name="price" value="200000"/>     
    7      </bean>     

     

    结果和不用 @Aotuwired一样,都可以

     还可以写在setter上

     1       //Person类
     2    public class Person {    
     3        private Car car;
     4         //@Aotuwired  
     5        public Car setCar(Car car){
     6              this.car=car;
     7                }
     8  }

     

     

    回到注解上面的例子:

     1     //UserController.java
     2  package com.guigu.spring.beans.annotation.controller;
     3  import org.springframework.stereotype.Controller;
     4   
     5   @Controller
     6   public class UserController {
     7   
     8       public void execute(){
     9           System.out.println("UserController execute...");
    10      }
    11  }

     

     1    // main函数
     2   public class Main {
     3  
     4      public static void main(String[] args) {
     5          private UserController userController;
     6          ApplicationContext ctx =new ClassPathXmlApplicationContext("beans-annotation.xml");         
     7         userController.execute();  // 报错
     8  }  
    9
    }

     

    在main函数声明userController然后直接调用它的方法,这样显然不行,因为userController都还没有创建,这时用@Autowired就很简单

     1      // main函数
     2     public class Main {
     3    
     4        public static void main(String[] args) {
     5            //@Autowired
     6            private UserController userController;
     7            ApplicationContext ctx =new ClassPathXmlApplicationContext("beans-annotation.xml");         
     8            userController.execute();//不报错
     9    }  
    10   }

     

    这样,就自动配置创建了userController对象,可以直接使用

    注意①:@Autowired要想成功配置,得先扫描得到,就是UserController类一定要能被扫描到。

    注意②:@Autowired遇到相同两个类

     

     

     1          //UserRepository
     2     package com.guigu.spring.beans.annotation.repository;
     3     public interface UserRepository {
     4         
     5         void save();
     6     }
     7     
     8         //UserRepositoryImpl  继承 UserRepository
     9     package com.guigu.spring.beans.annotation.repository;
    10   import org.springframework.stereotype.Repository;
    11   
    12   @Repository("userRepository");   //这里
    13   public class UserRepositoryImpl implements UserRepository {
    14   
    15       @Override
    16       public void save() {
    17           System.out.println("UserRepositoryImpl Save...");
    18       }
    19    //UserRepositoryImpl2  继承 UserRepository
    20    @Repository
    21    public class UserRepositoryImpl2 implements UserRepository {
    22   
    23       @Override
    24      public void save() {
    25           System.out.println("UserRepositoryImpl2 Save...");
    26       }
    27   }

     

     1        // main函数
     2       public class Main {
     3      
     4          public static void main(String[] args) {
     5              //@Autowired
     6              private UserRepository userRepository ;
     7              ApplicationContext ctx =new ClassPathXmlApplicationContext("beans-annotation.xml");         
     8              userRepository .save();
     9      }  
    10    }

     

    main函数中有@Autowired,自动创建对象,但UserRepository 类却有两个接口,它要去创建哪一个呢?

     :默认情况下,若有两个,去找名字相同的,就是还没实例的这个userRepository ,若找到和它名字一样的,上面 @Repository("userRepository"); 写了名字,那就找它了。

     若不是这样写@Repository("userRepository");而是 @Repository(),那就报错了。

    注意③:解决②的另一个方法

     若@Repository("userRepository");改成@Repository(),main函数会报错。

     改一下main函数

     1          // main函数
     2         public class Main {
     3        
     4            public static void main(String[] args) {
     5                //@Autowired
     6                //Qualifier("userRepositoryImpl ")
     7                private UserRepository userRepository ;
     8                ApplicationContext ctx =new ClassPathXmlApplicationContext("beans-annotation.xml");         
     9                userRepository .save();
    10        }  
    11     }

     

    Qualifier("userRepositoryImpl ");表示去找userRepositoryImpl 实例,这样也解决了。

     

  • 相关阅读:
    Oracle 11g R2性能优化 SQL TRACE
    Oracle 11g R2创建数据库之手工建库方式
    Oracle 11g R2创建数据库之DBCA静默方式
    CentOS 7静默安装Oracle 11g R2数据库软件
    如何在Windows上使用Git创建一个可执行脚本?
    我们为什么推荐在Json中使用string表示Number属性值?
    [麻雀虽小,五脏俱全] 之网站重写之路
    2020年必须掌握的硬核技能k8s
    [半翻] 设计面向DDD的微服务
    Quartz.net在集群环境下的 部署任务的姿势
  • 原文地址:https://www.cnblogs.com/ooooevan/p/5808692.html
Copyright © 2020-2023  润新知