实现功能

以上的代码我们发现。我们都是将@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支持组件注解限制(七)的更多相关文章

  1. 一起写框架-Ioc内核容器的实现-基础功能-ComponentScan支持多包扫描(六)

    实现功能 1.我们看到@ComponentScan注解一个开始定义就是需要支持,扫描多个包,将多个包的类名获取到.现在就实现这个功能. 实现思路 根据传入的字符串数组,获得多个包下的类全限制名. 实现 ...

  2. 一起写框架-Ioc内核容器的实现-基础功能-ComponentScan(四)

    功能说明 该步骤实现的功能包括: 1. 启动程序时,将@ComponentScan加载的类,创建对象并放在容器里面. 2. 通过ApplicatoinContext的getBean()方法获得容器里面 ...

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

    实现功能 --前面实现的代码-- 默认的对象名就类名.不符合Java的命名规范.我们希望默认的对象名首字母小写. 实现思路 创建一个命名规则的帮助类.实现将对大写开头的对象名修改为小写开头. 实现步骤 ...

  4. 一起写框架-Ioc内核容器的实现-基础功能-getBean(五)

    实现的功能 1. 启动程序时,将@ComponentScan加载的类,创建对象并放在容器里面.(查看上一篇文) 2. 通过ApplicatoinContext的getBean()方法获得容器里面的对象 ...

  5. 一起写框架-Ioc内核容器的实现-基础API的定义(三)

    Ioc内核要解决的问题 1.被调用方,在程序启动时就要创建好对象,放在一个容器里面. 2.调用方使用一个接口或类的引用(不用使用new),就可以创建获得对象. 解决这个两个问题的思路 1.定义一个对象 ...

  6. 自己动手写框架——IoC的实现

    先看看 IoC百度百科 优化过程 namespace Test { class Program { static void Main(string[] args) { //场景 某公司客服要回访一些客 ...

  7. 用C写一个web服务器(一) 基础功能

    .container { margin-right: auto; margin-left: auto; padding-left: 15px; padding-right: 15px } .conta ...

  8. spring框架--IOC容器,依赖注入

    思考: 1. 对象创建创建能否写死? 2. 对象创建细节 对象数量 action  多个   [维护成员变量] service 一个   [不需要维护公共变量] dao     一个   [不需要维护 ...

  9. 一起写框架-控制反转(Ioc)概述(二)

    控制反转概述 控制反转(Inversion of Control,英文缩写为IoC),就是将代码的调用的控制权,由调用方转移给被调用方. 如图:修改代码A类的代码,才能将B类的对象换成C类.代码的控制 ...

随机推荐

  1. ESLint可共享配置发布,团队自定义ESLint规则新鲜出炉

    ESLint于2013年6月份推出,至今4个年头,最新版本v4.8.0.它是目前主流的用于Javascript和JSX代码规范检查的利器,很多大公司比如Airbnb和Google均有一套自己的Java ...

  2. Jmeter测试HTTPS接口

    (以支付宝网站为例:https://memberprod.alipay.com/account/reg/index.htm) 浏览器:chrome 一.网页上导出证书 1.点击浏览器小锁--" ...

  3. PS+HTML测试

    PS: 1. 写出标尺.参考线.网格线.放大和缩小的快捷键 2. 写出RGB模式和CMYK颜色模式里每一个字母代表什么颜色 3. 写出暖色和冷色各3种 4. 写出常用的抠图工具(6个以上) 5. 写出 ...

  4. Sql Server合并多行询数据到一行:使用自连接、FOR XML PATH('')、STUFF或REPLACE函数

    示例表 tb 数据如下 id value ----- 1 aa 1 bb 2 aaa 2 bbb 2 ccc SELECT id, [val] = ( SELECT [value] + ',' FRO ...

  5. NOIP初赛 之 哈夫曼树

    哈夫曼树 种根据我已刷的初赛题中基本每套的倒数第五或第六个不定项选择题就有一个关于哈夫曼树及其各种应用的题,占:0-1.5分:然而我针对这个类型的题也多次不会做,so,今晚好好研究下哈夫曼树: 概念: ...

  6. Ricequant-米筐金工-估值因子

    Ricequant米筐金工--因子分析 作者:戴宇.小湖 上一篇介绍了单因子检验是因子分析前重要的一个步骤,是构建因子库.建立因子模型的基础,这篇报告首先对常见估值因子进行初步的检验. 第一篇.估值因 ...

  7. Hibernate 学习笔记 - 1

    一.Hibernate 的环境搭建.配置及 HelloWorld 1.在 Eclipse 中搭建 Hibernate 环境 下载 Hibernate 离线 jar 包(jbosstools-4.4.4 ...

  8. MXBridge - 插件式JS与OC交互框架

    概述 MXBridge,提供一个插件式的JavaScript与Objective-C交互的框架,通过JavaScriptCore实现,插件式扩展Obejctive-C接口以供JavaScript调用. ...

  9. webview的javascript与Native code交互

    http://my.oschina.net/u/1376187/blog/172296 项目中使用了webview显示网页,其中需要网页和native方法有交互,搜索到一篇文章,转发分享一下: === ...

  10. Linux 进程与信号的概念和操作

    进程 主要参考: http://www.bogotobogo.com/Linux/linux_process_and_signals.php 信号与进程几乎控制了操作系统的每个任务. 在shell中输 ...