一起写框架-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类.代码的控制 ...
随机推荐
- 童话故事 --- 通信协议之 HDLC 浅析
高飞狗: "高飞的白鹭浮水的鹅,唐诗里有画-" 布鲁托: "高飞狗,又在做你的高飞梦哪!" 高飞狗: "哈罗,布鲁托,这几天好郁闷呐!" 布 ...
- String+ String.Concat String.Format StringBuilder 之间的性能测试
找到一篇国外的代码,专门来测试这个, String+ String.Concat String.Format StringBuilder 前三个在100个左右字符串差不多, String.Concat ...
- cors解决ajax请求跨域问题
Access-Control-Allow-Origin: * 适用tomcat部署的项目 在web.xml里添加以下内容 <filter> <filter-name>CorsF ...
- ch1-vuejs基础入门(hw v-bind v-if v-for v-on v-model 应用组件简介 小案例)
1 hello world 引入vue.min.js 代码: ----2.0+版本 <div id="test"> {{str}} </div> <s ...
- Jquery cookie操作示例,写入cookie,读取cookie,删除cookie
<html> <head> <meta name="viewport" content="width=device-width" ...
- 项目常见函数封装,基于Jquery
/// <reference path="jquery-1.8.0.min.js" /> /* * DIV或元素居中 * @return */ jQuery.fn.mC ...
- 广州图书馆借阅抓取——httpClient的使用
欢迎访问我的个人网站,要是能在GitHub上对网站源码给个star就更好了. 搭建自己的网站的时候,想把自己读过借过的书都想记录一下,大学也做过自己学校的借书记录的爬取,但是数据库删掉了==,只保留一 ...
- Java集合源码分析(二)Linkedlist
前言 前面一篇我们分析了ArrayList的源码,这一篇分享的是LinkedList.我们都知道它的底层是由链表实现的,所以我们要明白什么是链表? 一.LinkedList简介 1.1.LinkedL ...
- Emgu.CV(一)
由于这块的知识不少,会分好几期写完 什么是OpenCV? OpenCV是一个基于(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows和Mac OS操作系统上.它轻量级而且高效--由一 ...
- CSS3动画 transition和animation的用法和区别
transition和animation都是CSS3新增的特性,使用时需要加内核 浏览器 内核名称 W3C IE -ms- Chrome/Safari -webkit- Firefoc - ...