zoukankan      html  css  js  c++  java
  • 一起写框架-Ioc内核容器的实现-基础功能-组件注解支持自定义的对象名(九)

    实现功能

    如果扫描组件注解(@Controller,@Service,@Repository,@Component)默认对象名,已经实现了默认使用首字母小写类名的作为对象名。

    但,现实需求中。我们有时候希望可以自己定义对象的名。

    实现思路

    1.获得扫描组件注解的name属性的值。

    2.将这个值作为对象名

    实现步骤

    1.AbstractApplicationContext增加一个方法getComponentOfName,用于判断组件注解是否设置了name属性。如果设置了就获得该值

     1 /**
     2      * 获得组件的对象名
     3      * 
     4      * @param classType
     5      * @return
     6      */
     7     private String getComponentOfName(Class<?> classType) {
     8         //获得四个组件注解的对象
     9         Component component = classType.getDeclaredAnnotation(Component.class);
    10         Service service = classType.getDeclaredAnnotation(Service.class);
    11         Controller controller = classType.getDeclaredAnnotation(Controller.class);
    12         Repository repository = classType.getDeclaredAnnotation(Repository.class);
    13         //判断注解对象是否为空,注解对象的的name属性是否有值
    14         if (component != null) {
    15             if (!"".equals(component.name()) && component.name() != null) {
    16                 return component.name();
    17             }
    18         } 
    19         if (service != null) {
    20             if (!"".equals(service.name()) && service.name() != null) {
    21                 return service.name();
    22             }
    23         } 
    24         if (controller != null) {
    25             if (!"".equals(controller.name()) && controller.name() != null) {
    26                 return controller.name();
    27             }
    28         } 
    29         if (repository != null) {
    30             if (!"".equals(repository.name()) && repository.name() != null) {
    31                 return repository.name();
    32             }
    33         }
    34         return null;
    35 
    36     }

    2.修改AbstractApplicationContext类的构造方法。标红处

     1 /**
     2      * 将容器操作加载创建对象的代码写抽象类里面,这样可以方便以后扩展多种实现。
     3      * 
     4      * @param classType
     5      */
     6     public AbstractApplicationContext(Class<?> classType) {
     7         // 判断配置类是否有Configuration注解
     8         Configuration annotation = classType.getDeclaredAnnotation(Configuration.class);
     9         if (annotation != null) {
    10             // 获得组件扫描注解
    11             ComponentScan componentScan = classType.getDeclaredAnnotation(ComponentScan.class);
    12             // 获得包名
    13             this.basePackage = componentScan.basePackages();
    14             // 根据包名获得类全限制名
    15             // Set<String> classNames =
    16             // PackageUtils.getClassName(this.basePackage[0], true);
    17             // 将扫描一个包,修改为多个包
    18             Set<String> classNames = PackageUtils.getClassNames(this.basePackage, true);
    19             // 通过类名创建对象
    20             Iterator<String> iteratorClassName = classNames.iterator();
    21             while (iteratorClassName.hasNext()) {
    22 
    23                 String className = iteratorClassName.next();
    24                 // System.out.println(className);
    25                 try {
    26                     // 通过类全名创建对象
    27                     Class<?> objectClassType = Class.forName(className);
    28                     /*
    29                      * 判断如果类权限名对应的不是接口,并且包含有@Component|@Controller|@Service|
    30                      * @Repository 才可以创建对象
    31                      */
    32                     if (this.isComponent(objectClassType)) {
    33                         Object instance = objectClassType.newInstance();
    34                         // 修改为,默认对象支持首字符小写
    35                         String objectName=null;
    36                         //获得组件注解的name属性值
    37                         String componentName = this.getComponentOfName(objectClassType);
    38                     
    39                         if(componentName==null){
    40                             //如果组件注解的name属性没有值,使用默认命名对象
    41                             objectName= NamingUtils.firstCharToLower(instance.getClass().getSimpleName());
    42                         }else{
    43                             //如果组件注解的name属性有值,使用自定义命名对象
    44                             objectName=componentName;
    45                         }
    46                         this.getContext().addObject(objectName, instance);
    47                     }
    48                 } catch (InstantiationException e) {
    49                     e.printStackTrace();
    50                 } catch (IllegalAccessException e) {
    51                     e.printStackTrace();
    52                 } catch (ClassNotFoundException e) {
    53                     e.printStackTrace();
    54                 }
    55             }
    56         }
    57     }

    测试代码

    1.修改UserService类的组件注解

     1 package ioc.core.test.service;
     2 
     3 import ioc.core.annotation.stereotype.Service;
     4 
     5 /**
     6  * 一个普通的类,用于测试是否可以创建对象
     7  * @author ranger
     8  *
     9  */
    10 @Service(name="uService")
    11 public class UserService {
    12     
    13     public void login(){
    14         System.out.println("-登录Service-");
    15     }
    16 
    17 }

    2.测试类

     1 package ioc.core.test;
     2 
     3 import org.junit.Test;
     4 
     5 import ioc.core.impl.AnntationApplicationContext;
     6 import ioc.core.test.config.Config;
     7 import ioc.core.test.service.UserService;
     8 
     9 public class AnntationApplicationContextTest {
    10     
    11     @Test
    12     public void login(){
    13         try {
    14             AnntationApplicationContext context=new AnntationApplicationContext(Config.class);
    15             UserService userService = context.getBean("uService", UserService.class);
    16             userService.login();
    17             System.out.println(context.getContext().getObjects());
    18         
    19         } catch (Exception e) {
    20             e.printStackTrace();
    21         }
    22     }
    23 
    24 }

    3.测试结果

  • 相关阅读:
    WPF 文本滚动效果 渐变效果
    Unity3D 学习——入门资料整理
    命名管道 问题:信号灯超时问题
    Nginx 遇到的问题
    Nginx的安装配置 例子
    03 Spring的父子容器
    02 浅析Spring的AOP(面向切面编程)
    03 JVM的垃圾回收机制
    02 Java类的加载机制
    01 深入理解JVM的内存区域
  • 原文地址:https://www.cnblogs.com/zhuyuejiu/p/7819485.html
Copyright © 2011-2022 走看看