一块儿写框架-Ioc内核容器的实现-基础功能-ComponentScan支持组件注解限制(七)

实现功能

以上的代码咱们发现。咱们都是将@ComponentScan扫描的路径下的全部类都加载到容器中的。java

而实际需求,咱们并不但愿全部的类都建立对象,而是加了组件注解@Controller,@Service,@Repository,@Component的类才建立对象函数

而不加这些标识的类不须要建立对象。测试

 

所谓本章就是实现经过组件注解限制哪些类是能够建立对象的,哪些是不能够的。this

 

实现思路

根据得到的类全限制名,得到它的Class对象。经过Class对象判断类的声明上是否有组件注解。有就建立对象,没有就不建立。spa

 

实现步骤

1.定义四个组件注解code

--Controller-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 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-blog

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类,修改构造函数标红处的代码

 

 1   /**
 2       * 将容器操做加载建立对象的代码写抽象类里面,这样能够方便之后扩展多种实现。
 3       * @param classType
 4       */
 5     public AbstractApplicationContext(Class<?> classType) {
 6          //判断配置类是否有Configuration注解
 7          Configuration annotation = classType.getDeclaredAnnotation(Configuration.class);
 8          if(annotation!=null){
 9              //得到组件扫描注解
10              ComponentScan componentScan = classType.getDeclaredAnnotation(ComponentScan.class);
11              //得到包名
12              this.basePackage = componentScan.basePackages();
13              //根据包名得到类全限制名
14              //Set<String> classNames = PackageUtils.getClassName(this.basePackage[0], true);
15              //将扫描一个包,修改成多个包
16              Set<String> classNames = PackageUtils.getClassNames(this.basePackage, true);
17              //经过类名建立对象
18              Iterator<String> iteratorClassName = classNames.iterator();
19              while(iteratorClassName.hasNext()){
20                  
21                  String className = iteratorClassName.next();
22                  //System.out.println(className);
23                  try {
24                      //经过类全名建立对象
25                      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                      }
36                 } catch (InstantiationException e) {
37                     e.printStackTrace();
38                 } catch (IllegalAccessException e) {
39                     e.printStackTrace();
40                 } catch (ClassNotFoundException e) {
41                     e.printStackTrace();
42                 }
43              }
44          }
45     }

 测试代码

1.配置类,扫描ioc.core.test的全部类

 1 package ioc.core.test.config;
 2 
 3 import ioc.core.annotation.ComponentScan;
 4 import ioc.core.annotation.Configuration;
 5 
 6 //使用定义@Configuration定义该类是一个配置类
 7 @Configuration
 8 //使用ComponentScan设置扫描包的路径
 9 @ComponentScan(basePackages={"ioc.core.test"})
10 public class Config {
11 
12 }

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,说明测试成功。

相关文章
相关标签/搜索