spring自定义注解

为什么要演示这个spring自定义注解呢,以前我觉得代码什么基本都看的懂,但是这天一个老师给我们讲spring基础的时候我懵逼了,他这将的不是教会你简单使用,直接进底层的。直接实现自定义注解,许多公司技术封装也就是这样,也就是spring现在这个反射读取类的过程。

大概过程就是先重写这几个注解,然后在平常业务中调用这些注解,反射读取这个包下的文件,将他们加载进去,通过map来存每一个类名和反射生成的对象,使用的时候通过map的key来找到对应的对象,再去调用。也就是spring容器的作用进行了一个自定义实现的过程。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210526155126207.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzcyNDE0,size_16,color_FFFFFF,t_70

anntation下面

package com.example.annotation;
import org.springframework.beans.factory.annotation.Autowired;

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;
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface UdaAutowired {
    boolean required() default true;
}
package com.example.annotation;
import org.springframework.stereotype.Indexed;
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;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface UdaComponent {
    String value() default "";
}

package com.example.annotation;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface  UdaController {
    String value() default "";
}
package com.example.annotation;
import java.lang.annotation.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.web.bind.annotation.Mapping;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface UdaRequestMapping {
    String value() default "";

}

package com.example.annotation;
import java.lang.annotation.*;
import org.springframework.stereotype.Component;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface UdaService {
    String value() default "";
}

autoconfig

package com.example.autoconfig;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class UdaBeanFactory {
    private Map<String ,Object>beanMap=new HashMap<String,Object>();
    //beanMap存实列的key,value;
    public Object createBean(Class<?> clz,String name) throws IllegalAccessException, InstantiationException {  //clz: com.example.ioc.dao.UserDao  name:就是注解上加的东西比如@UdaComponent(“你是谁”),说就是你是谁几个字
        Object instance=clz.newInstance();
        //实例化一个Bean工厂类
        if(name==null||name.length()==0){   //name:"u"  因为我在注解里加了个字母u
            beanMap.put(lowerCase(clz.getSimpleName()),instance);
        }else {
            beanMap.put(name,instance);
        }
        beanMap.put(clz.getName(),instance); //这个beanMap里面存了两个元素,一个是key="com.example.ioc.dao.UserDao" value="UserDao@582" 一个是key="u",value="UserDao@582"
        return  instance;
    }
    private String lowerCase(String str){
        return str.substring(0,1).toLowerCase() + str.substring(1);
    }
    public  void injectionFileId(Class<?>clz, Field field)throws IllegalAccessException{
        Class<?> type=field.getType();
        Object curObj =beanMap.get(clz.getName()); //通过类名获取到这个对象,也就是UserService@719
        field.setAccessible(true);
        Object injectObj =beanMap.get(type.getName()); //成员变量上的这个UserDao对象,也就是UserDao@582
        field.set(curObj,injectObj);
    }
    public Map<String,Object> getBeans(){
        return beanMap;
    }
    @SuppressWarnings("unchecked")
    public <T> T getBean(Class<?> clz) {
        return (T) beanMap.get(clz.getName());
    }
    @SuppressWarnings("unchecked")
    public <T> T getBean(String name) {
        return (T) beanMap.get(name);
    }
}
package com.example.autoconfig;
import com.example.annotation.*;

import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author : XuZhiYong
 * @Description :
 * @Date : Created in 11:20 2021/5/21
 */
//自定义Spring容器
public class UdaSpringContext {
    private UdaBeanFactory beanFactory = new UdaBeanFactory();
    public void initContext(String path) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        path = path.replace(".", "/");  //将com.example.ioc转变成com/example/ioc
        ClassLoader classLoader = UdaSpringContext.class.getClassLoader();//类加载器这个是自定义的所以是classLoader:Launcher$AppClassLoader@497
        URL url = classLoader.getResource(path);//path: "com/example/ioc" classLoader:Launcher$AppClassLoader@497   url:file:/C:/Users/study/IdeaProjects/springself/target/classes/com/example/ioc
        //通过类加载器取得URL地址
        File file = new File(url.getPath());
        //取得根目录下所有的文件地址
        List<File> clzList = new ArrayList<File>();
        getFileList(file, clzList);
        List<Class<?>> classList = new ArrayList<Class<?>>();
        for (File clz : clzList) {
            //C:\Users\study\IdeaProjects\springself\target\classes\com\example\ioc\dao\UserDao.class
            //C:\Users\study\IdeaProjects\springself\target\classes\com\example\ioc\service\Userservice.class 这两个
            String apath = clz.getAbsolutePath();
            //得到绝对地址
            apath = apath.replace("\\", "/");
            int pre = apath.indexOf(path);  //判断这个路径出现/com/example/ioc的位置,就是第54
            String clzName = apath.substring(pre);  //从第54的位置截断就剩下com.example.ioc.dao.UserDao
            clzName = clzName.replace(".class", "").replace("/", ".");
            //得到类名
            Class<?> loadClass = classLoader.loadClass(clzName);  //clzName:"class com.example.ioc.dao.UserDao" 因为只是读取到了这个类名,并没有加载运行
            //把类加载到运行池中
            //扫描带有UdaComponent注解的
            UdaComponent annotation = loadClass.getAnnotation(UdaComponent.class); //loadClass clzName:"class com.example.ioc.dao.UserDao"
            //扫描带有UdaService注解的
            UdaService serviceAnno=loadClass.getAnnotation(UdaService.class);  //annotation:@com.example.annotation.UdaComponent(value=u)
            //扫描取得项目注解,先扫描的dao里面出现的@UdaComponent注解
            if (annotation != null) {
                String name = annotation.value();
                //注解定义的名字
                beanFactory.createBean(loadClass, name);
                //创建一个Bean工厂
                classList.add(loadClass);
            }else if (serviceAnno!=null){
                String name = serviceAnno.value();
                //注解定义的名字
                beanFactory.createBean(loadClass, name);
                //创建一个Bean工厂
                classList.add(loadClass);
            }
//            UdaController controllerAnno=loadClass.getAnnotation(UdaController.class);
//            if (controllerAnno!=null){
//                beanFactory.createBean(loadClass,null);
//                //类路径
//                UdaRequestMapping clzMapping=loadClass.getAnnotation(UdaRequestMapping.class);
//                String clzUrl=clzMapping==null?"":clzMapping.name();
//                //接下来检查所有的public方法是否带有UpdRequestMapping注解修饰的
//                checkMethod(loadClass,createBean,clzUrl);
//                classList.add(loadClass);
//            }
            for(Class<?> LoadClass : classList){
                injection(loadClass);
            }
           /* if(controllerAnno != null){

            }*/
        }


    }
    //判断哪个是文件,如果是文件就加载到clzList中
    private void getFileList(File file, List<File> clzList) {
        if (file.isDirectory()) {   //如果该文件是个目录,就再进去一层
            File[] files = file.listFiles();
            for (File f : files) {
                getFileList(f, clzList);

            }
        } else {
            clzList.add(file);  //C:\Users\study\IdeaProjects\springself\target\classes\com\example\ioc\dao\UserDao.class
            //C:\Users\study\IdeaProjects\springself\target\classes\com\example\ioc\service\Userservice.class 这两个类就添加到列表里面了
        }
    }

    private void injection(Class<?> loadClass) throws  IllegalAccessException{   //这里开始进行反射
        Field[] fields=loadClass.getDeclaredFields();
        for(Field field:fields){
            UdaAutowired fieldAnno =field.getAnnotation(UdaAutowired.class);  //在service里面定义了一个成员变量,所以会执行进来
            if(fieldAnno!=null){
                beanFactory.injectionFileId(loadClass,field);
            }
        }
    }
    public <T> T getBean(Class<?> clz) {
        return beanFactory.getBean(clz);
    }

    public <T> T getBean(String name){
        return beanFactory.getBean(name);
    }
    public Map<String,Object> getBeans(){
        return beanFactory.getBeans();
    }
}

ioc下

package com.example.ioc.controller;

import org.springframework.stereotype.Component;

@Component
public class UserController {
}

package com.example.ioc.dao;
import com.example.annotation.UdaComponent;
@UdaComponent("u")
public class UserDao {
    public void addUser(String name){
        System.out.println(String.format("用户[%s]添加成功",name));
    }
}
package com.example.ioc.service;
import com.example.annotation.UdaAutowired;
import com.example.annotation.UdaService;
import com.example.ioc.dao.UserDao;
@UdaService
public class Userservice {
    @UdaAutowired
    UserDao userDao;
    public void show(String name){
        userDao.addUser(name);
    }
}

package com.example;

import com.example.autoconfig.UdaSpringContext;
import com.example.ioc.dao.UserDao;
import com.example.ioc.service.Userservice;

public class TestApplication {
    public static void main(String[] args){
        UdaSpringContext context=new UdaSpringContext();
        //触发自定义容器
        try {
            System.out.println("开始初始化容器");
            long t=System.currentTimeMillis();
            context.initContext("com.example.ioc");  //这是平常我们放service,dao包的地方
            //扫描包下所有文件加载到容器里面
            System.out.println("初始化容器成功,cost time:"+(System.currentTimeMillis()-t));
            Userservice controller1=context.getBean(Userservice.class);
            controller1.show("与子安你是个xx");
            UserDao userDao=context.getBean(UserDao.class);
            userDao.addUser("与子安真是个奴婢");
    		 showBeans(context.getBeans());
        }catch (Exception e){
            e.printStackTrace();
        }
    }
     private static void showBeans(Map<String,Object> map){
        for (String key:map.keySet()){
            System.out.println("健值为"+key+",对象为"+map.get(key));
        }
    }
}

效果图如下

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值