一起写框架-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.测试结果

时间: 2024-11-08 17:17:36

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

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

实现功能 --前面实现的代码-- 默认的对象名就类名.不符合Java的命名规范.我们希望默认的对象名首字母小写. 实现思路 创建一个命名规则的帮助类.实现将对大写开头的对象名修改为小写开头. 实现步骤 1.创建一个命名规则帮助类 1 package ioc.core.utils; 2 3 /** 4 * 创建命名规则帮助类 5 * 6 * @author ranger 7 * 8 */ 9 public class NamingUtils { 10 /** 11 * 将类名修改为对象名,首字母小

一起写框架-Ioc内核容器的实现-基础功能-ComponentScan支持组件注解限制(七)

实现功能 以上的代码我们发现.我们都是将@ComponentScan扫描的路径下的所有类都加载到容器中的. 而实际需求,我们并不希望所有的类都创建对象,而是加了组件注解@Controller,@Service,@Repository,@Component的类才创建对象 而不加这些标识的类不需要创建对象. 所谓本章就是实现通过组件注解限制哪些类是可以创建对象的,哪些是不可以的. 实现思路 根据获得的类全限制名,获得它的Class对象.通过Class对象判断类的声明上是否有组件注解.有就创建对象,没

一起写框架-Ioc内核容器的实现-对象的调用[email&#160;protected]注解注入容器的对象(十二)

实现功能 现实需求中,有一些类似无法加入扫描组件注解的.如jdk里面的类. 那么框架必须要支持将没有组件注解标识的类也可以有一个方式注入到容器里面. 那么,我们通过类似Spring的@Bean的方案,来实现这个需求. 通过在配置类的方法的上面,使用@Bean注解,将返回的对象加到容器中. 实现思路 获得有@Configuration注解标识的类.检索它的方法,如果有@Bean,执行这个方法并将返回的对象放在容器中. 实现步骤 1.定义一个Bean注解 1 package ioc.core.ann

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

实现功能 需求:在类的成员属性使用@Autowirde注解注入容器中的对象. 实现思路 要实现这个功能.我们首先要思考一个问题:类与类的关系是在调用的建立的,还是说在创建对象的时候就就将建立了? ---我实现的方案是,在在程序启动后,所有对象创建后直接就将对象的属性和属性之间的关系创建了.接下来我就用这个思路来实现,将根据@Autowirde建立对象与对象之间的关系. 为什么一定要对象全部创建后再实现对象与对象直接的关系呢? 这个是逻辑问题,如果对象没有创建完就建立对象与对象之间的关系,人家都还

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

实现功能 就是在方法的上面加入@Autowired注解,容器中的对象会注入到对应类型的参数. 注意:暂时实现注入一个对象.所有方法的参数列表的参数只能有一个. 实现思路 其实实现的思路和给字段注入的逻辑是一样的.遍历类所有的方法有没有@Autowired,有的就给它赋予容器中对应的对象. 实现步骤 1. 在AbstractApplicationContext类增加两个方法区分属性注入(autowiredField)和方法注入(autowiredMethod) 1 /** 2 * 属性注入 3 *

Spring框架IOC容器和AOP解析

主要分析点: 一.Spring开源框架的简介  二.Spring下IOC容器和DI(依赖注入Dependency injection) 三.Spring下面向切面编程(AOP)和事务管理配置  一.Spring开源框架的简介  Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来.它是为了解决企业应用开

从零开始手写 spring ioc 框架,深入学习 spring 源码

IoC Ioc 是一款 spring ioc 核心功能简化实现版本,便于学习和理解原理. 创作目的 使用 spring 很长时间,对于 spring 使用非常频繁,实际上对于源码一直没有静下心来学习过. 但是 spring 源码存在一个问题,那就是过于抽象,导致学习起来成本上升. 所以本项目由渐入深,只实现 spring 的核心功能,便于自己和他人学习 spring 的核心原理. spring 的核心 Spring 的核心就是 spring-beans,后面的一切 spring-boot,spr

Spring框架—— IOC容器和Bean的配置

 1 IOC和DI ①IOC(Inversion of Control):反转控制. 在应用程序中的组件需要获取资源时,传统的方式是组件主动的从容器中获取所需要的资源,在这样的模式下开发人员往往需要知道在具体容器中特定资源的获取方式,增加了学习成本,同时降低了开发效率. 反转控制的思想完全颠覆了应用程序组件获取资源的传统方式:反转了资源的获取方向--改由容器主动的将资源推送给需要的组件,开发人员不需要知道容器是如何创建资源对象的,只需要提供接收资源的方式即可,极大的降低了学习成本,提高了开发的效

一起写框架-说在前面的话(一)

本人的想法: 互联网中,一堆框架.浮躁的社会,到处都是秒天秒地的广告. 各种Struts,Spring,Hibernate,Mybatis的学习教程充斥互联网.让人有一种错觉,只要学会框架,就可以解决一切问题! 而我,从入行就开始的思考一个问题:作为一个Java程序员,难道仅仅就会几个框架就满足了吗? 有没有想过试试,自己也写一个! 然而:事与人违!充满冲劲的时候,小白一个,什么也不懂.当开始入行后,一直忙碌活地为生存而活着,早已将这个曾经强烈的欲望压到了脑后. 最近,终于开始有了一点点时间,而