一起写框架-Ioc内核容器的实现-基础功能-ComponentScan支持组件注解限制(七)
实现功能
以上的代码我们发现。我们都是将@ComponentScan扫描的路径下的所有类都加载到容器中的。
而实际需求,我们并不希望所有的类都创建对象,而是加了组件注解@Controller,@Service,@Repository,@Component的类才创建对象
而不加这些标识的类不需要创建对象。
所谓本章就是实现通过组件注解限制哪些类是可以创建对象的,哪些是不可以的。
实现思路
根据获得的类全限制名,获得它的Class对象。通过Class对象判断类的声明上是否有组件注解。有就创建对象,没有就不创建。
实现步骤
1.定义四个组件注解
--Controller-
package ioc.core.annotation.stereotype; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)
@Target(value=ElementType.TYPE)
@Documented
public @interface Controller {
/**
* 用于设置对象名的属性
* @return
*/
String name() default ""; }
--Service--
package ioc.core.annotation.stereotype; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* 服务层的组件注解定义
* @author ranger
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value=ElementType.TYPE)
@Documented
public @interface Service {
/**
* 定义用于设置类的对象名的属性,默认值为空字符串
* @return
*/
String name() default ""; }
-Repository-
package ioc.core.annotation.stereotype; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)
@Target(value=ElementType.TYPE)
@Documented
public @interface Repository {
/**
* 设置对象名的属性
* @return
*/
String name() default ""; }
--Component--
package ioc.core.annotation.stereotype; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)
@Target(value=ElementType.TYPE)
@Documented
public @interface Component {
/**
* 设置对象名的属性
* @return
*/
String name() default ""; }
2.修改AbstractApplicationContext类,增加了一个isComponent方法判断是否是组件类
/**
* 判断是否是组件
* @param classType
* @return
*/
private boolean isComponent(Class<?> classType){
//如果是接口,就不能创建对象,直接返回false
if(classType.isInterface()){
return false;
}
Component component = classType.getDeclaredAnnotation(Component.class);
Service service = classType.getDeclaredAnnotation(Service.class);
Controller controller = classType.getDeclaredAnnotation(Controller.class);
Repository repository = classType.getDeclaredAnnotation(Repository.class);
//判断只要有一个组件注解,就返回
if(component!=null||service!=null||controller!=null||repository!=null){
return true;
}
return false;
}
3.修改AbstractApplicationContext类,修改构造函数标红处的代码。
/**
* 将容器操作加载创建对象的代码写抽象类里面,这样可以方便以后扩展多种实现。
* @param classType
*/
public AbstractApplicationContext(Class<?> classType) {
//判断配置类是否有Configuration注解
Configuration annotation = classType.getDeclaredAnnotation(Configuration.class);
if(annotation!=null){
//获得组件扫描注解
ComponentScan componentScan = classType.getDeclaredAnnotation(ComponentScan.class);
//获得包名
this.basePackage = componentScan.basePackages();
//根据包名获得类全限制名
//Set<String> classNames = PackageUtils.getClassName(this.basePackage[0], true);
//将扫描一个包,修改为多个包
Set<String> classNames = PackageUtils.getClassNames(this.basePackage, true);
//通过类名创建对象
Iterator<String> iteratorClassName = classNames.iterator();
while(iteratorClassName.hasNext()){ String className = iteratorClassName.next();
//System.out.println(className);
try {
//通过类全名创建对象
Class<?> objectClassType = Class.forName(className);
26 /*
27 * 判断如果类权限名对应的不是接口并且包含有
28 * @Component|@Controller|@Service|@Repository
29 * 才可以创建对象
30 */
31 if(this.isComponent(objectClassType)){
32 Object instance = objectClassType.newInstance();
33 //将对象加到容器中,对象名就类全名
34 this.getContext().addObject(instance.getClass().getSimpleName(),instance);
35 }
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
测试代码
1.配置类,扫描ioc.core.test的所有类
package ioc.core.test.config; import ioc.core.annotation.ComponentScan;
import ioc.core.annotation.Configuration; //使用定义@Configuration定义该类是一个配置类
@Configuration
//使用ComponentScan设置扫描包的路径
@ComponentScan(basePackages={"ioc.core.test"})
public class Config { }
2.增加不同组件注解的普通类
--Controller测试类--
package ioc.core.test.controller; import ioc.core.annotation.stereotype.Controller; @Controller
public class UserController { public void login(){
System.out.println("-登录Controller-");
} }
-UserService--
package ioc.core.test.controller; import ioc.core.annotation.stereotype.Controller; @Controller
public class UserController { public void login(){
System.out.println("-登录Controller-");
} } package ioc.core.test.dao; import ioc.core.annotation.stereotype.Repository; @Repository
public class UserDAO { public void save(){
System.out.println("-save保存数据-");
} } package ioc.core.test.service; import ioc.core.annotation.stereotype.Service; /**
* 一个普通的类,用于测试是否可以创建对象
* @author ranger
*
*/
@Service
public class UserService { public void login(){
System.out.println("-登录Service-");
} }
-UserDAO--
package ioc.core.test.dao; import ioc.core.annotation.stereotype.Repository; @Repository
public class UserDAO { public void save(){
System.out.println("-save保存数据-");
} }
3.测试类输出容器内的对象
package ioc.core.test; import org.junit.Test; import ioc.core.impl.AnntationApplicationContext;
import ioc.core.test.config.Config; public class AnntationApplicationContextTest { @Test
public void login(){
try {
AnntationApplicationContext context=new AnntationApplicationContext(Config.class);
System.out.println(context.getContext().getObjects()); } catch (Exception e) {
e.printStackTrace();
}
} }
--测试结果--
加了组件注解的三个类的对象可以获得,没有加组件注解的Config类和AnntationApplicationContextTest,说明测试成功。
一起写框架-Ioc内核容器的实现-基础功能-ComponentScan支持组件注解限制(七)的更多相关文章
- 一起写框架-Ioc内核容器的实现-基础功能-ComponentScan支持多包扫描(六)
实现功能 1.我们看到@ComponentScan注解一个开始定义就是需要支持,扫描多个包,将多个包的类名获取到.现在就实现这个功能. 实现思路 根据传入的字符串数组,获得多个包下的类全限制名. 实现 ...
- 一起写框架-Ioc内核容器的实现-基础功能-ComponentScan(四)
功能说明 该步骤实现的功能包括: 1. 启动程序时,将@ComponentScan加载的类,创建对象并放在容器里面. 2. 通过ApplicatoinContext的getBean()方法获得容器里面 ...
- 一起写框架-Ioc内核容器的实现-基础功能-容器对象名默认首字母小写(八)
实现功能 --前面实现的代码-- 默认的对象名就类名.不符合Java的命名规范.我们希望默认的对象名首字母小写. 实现思路 创建一个命名规则的帮助类.实现将对大写开头的对象名修改为小写开头. 实现步骤 ...
- 一起写框架-Ioc内核容器的实现-基础功能-getBean(五)
实现的功能 1. 启动程序时,将@ComponentScan加载的类,创建对象并放在容器里面.(查看上一篇文) 2. 通过ApplicatoinContext的getBean()方法获得容器里面的对象 ...
- 一起写框架-Ioc内核容器的实现-基础API的定义(三)
Ioc内核要解决的问题 1.被调用方,在程序启动时就要创建好对象,放在一个容器里面. 2.调用方使用一个接口或类的引用(不用使用new),就可以创建获得对象. 解决这个两个问题的思路 1.定义一个对象 ...
- 自己动手写框架——IoC的实现
先看看 IoC百度百科 优化过程 namespace Test { class Program { static void Main(string[] args) { //场景 某公司客服要回访一些客 ...
- 用C写一个web服务器(一) 基础功能
.container { margin-right: auto; margin-left: auto; padding-left: 15px; padding-right: 15px } .conta ...
- spring框架--IOC容器,依赖注入
思考: 1. 对象创建创建能否写死? 2. 对象创建细节 对象数量 action 多个 [维护成员变量] service 一个 [不需要维护公共变量] dao 一个 [不需要维护 ...
- 一起写框架-控制反转(Ioc)概述(二)
控制反转概述 控制反转(Inversion of Control,英文缩写为IoC),就是将代码的调用的控制权,由调用方转移给被调用方. 如图:修改代码A类的代码,才能将B类的对象换成C类.代码的控制 ...
随机推荐
- Sequence query 好题啊
Sequence query Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Subm ...
- SpringMVC上传压缩文件,解压文件,并检测上传文件中是否有index.html
SpringMVC上传压缩文件,解压文件,并检测上传文件中是否有index.html 说明: 1.环境:SpringMVC+Spring+Tomcat7+JDK1.7 2.支持 zip和rar格式的压 ...
- mysql error 1130 hy000:Host 'localhost' is not allowed to connect to this mysql server 解决方案
ERROR 1130 (HY000): Host 'localhost' is not allowed to connect to this MySQL server D:\Wamp\mysql-\b ...
- dom4j之小小工具
dom4j经常不用,方法忘了又记,故做出读取xml和把document写入xml的小小工具~~~ /** * 读取document和将document对象写入到xml的小工具 * 使用该类必须给出do ...
- python 输出语句的写法
总结: 1.类似于C语言的格式化输出,先写转换符,再写待转换的对象. 2.与C语言不同的是,转换符和待转换的对象之间,不能用逗号分隔. #!/usr/bin/env python #print dig ...
- 初学者易上手的SSH-struts2 02Action获取表单数据-通配符
在上一章中,我们已经搭建好了struts2的一个开发环境,那么这一章就来做一个简单的登录功能,以及介绍和使用struts2里面一个重要的东西-通配符. 第一步,在WebContent下面新建一个log ...
- 从开发到部署会用到的 Docker 命令
本文的目的是理解容器开发在目标环境中部署的端到端流程,并列出这些操作所需的 Docker 命令.如果有任何Docker问题,请移步到最新最热的技术社区 IT帮 itbang.me 提问,短信通知专家来 ...
- EasyUI Dialog 窗体 布局记要
通常在窗体里放置的都是表单,或者使用分栏(Tab)来陈列信息也是非常的好用.在这里特别记录一下在窗体里同时放置表单和表格的设计思路. 仅放置一个表单 通常 Dialog 里只放一个表单,而且表单的行数 ...
- 最火的Android开源项目(一)
摘要:对于开发者而言,了解当下比较流行的开源项目很是必要.利用这些项目,有时能够让你达到事半功倍的效果.为此,CSDN特整理了GitHub上最受欢迎的Android及iOS开源项目,本文详细介绍了20 ...
- SpringBoot01 InteliJ IDEA安装、Maven配置、创建SpringBoot项目、属性配置、多环境配置
1 InteliJ IDEA 安装 下载地址:点击前往 注意:需要下载专业版本的,注册码在网上随便搜一个就行啦 2 MAVEN工具的安装 2.1 获取安装包 下载地址:点击前往 2.2 安装过程 到官 ...