一起写框架-Ioc内核容器的实现-基础功能-组件注解支持自定义的对象名

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一起写框架-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.测试结果

技术分享

 

以上是关于一起写框架-Ioc内核容器的实现-基础功能-组件注解支持自定义的对象名的主要内容,如果未能解决你的问题,请参考以下文章

一起写框架-Ioc内核容器的实现-基础功能-容器对象名默认首字母小写

一起写框架-Ioc内核容器的实现-对象的调用-@Bean注解注入容器的对象

一起写框架-Ioc内核容器的实现-对象的调用-属性注入容器的对象

一起写框架-Ioc内核容器的实现-对象的调用-方法注入容器的对象

Spring IOC核心功能快速入门

Spring如何实现IOC容器功能