一起写框架-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类.代码的控制 ...
随机推荐
- http://codeforces.com/contest/612/problem/D
D. The Union of k-Segments time limit per test 4 seconds memory limit per test 256 megabytes input s ...
- Android01-布局篇
在Android中,共有五种布局方式,分别是:LinearLayout(线性布局),FrameLayout(帧布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局) ...
- php里的抽象类和接口
//实例化类产生对象.//class fenbi//{// //普通成员,属于对象// public $length = "10cm";// //静态成员,静态变量,属于类.// ...
- NOIP 11.01 应试记录
快排代码 void quicksort(int left,int right) { int u,j,t,temp; if(letf>right) return; temp=a[left]; i= ...
- Linux jdk安装多个版本并进行切换
1. 上传jdk7 和 jdk8 包 2. 解压 [root@localhost webapps]# tar -zxvf /package/jdk-7u80-linux-x64.tar.gz 3. 配 ...
- Html事件冒泡
原以为span不同于input,事件冒泡会被父级标签吞噬,写了个测试事件冒泡的Demo,发现并不是想得那样.另外:event.stopPropagation()以及event.stopImmediat ...
- dotweb框架之旅 [一] - HelloWorld
一直想着,要系统性的写一些dotweb使用的文章,之前拖延了不少时间,今天,下定决定,算是正式的开始,也请大家一起监督. dotweb,是一款追求简约大方的go web框架,正如其github项目主页 ...
- IsKeyboardFocused -- 键盘焦点
<Trigger Property="IsKeyboardFocused" Value="true"> <!--<Setter Prop ...
- Linux向文件添加内容的几种方法
例如,要想test.txt文件添加内容"I am a boy",test.txt在当前目录中 方法一:vi编辑法 打开终端,输入vi test.txt 回车,按a或i进入编辑模式, ...
- XtraReports 入门教程
一个链接:http://www.cnblogs.com/springSky/tag/XtraReports%20%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B/ 与之相同功能 ...