若是掃描組件註解(@Controller,@Service,@Repository,@Component)默認對象名,已經實現了默認使用首字母小寫類名的做爲對象名。測試
但,現實需求中。咱們有時候但願能夠本身定義對象的名。this
1.得到掃描組件註解的name屬性的值。spa
2.將這個值做爲對象名code
1.在AbstractApplicationContext增長一個方法getComponentOfName,用於判斷組件註解是否設置了name屬性。若是設置了就得到該值component
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類的組件註解blog
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.測試結果get