简单的实现spring的全注解式开发通过自己创建注解来完成这个任务

创建的注解类

  1. 配置注解(configuration)(这个注解主要式为了区分开是否使用了这个注解的方式来代替这个配置文件)
package com.project1.AnnotationSpring;

import java.lang.annotation.*;


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

2.配置这个扫描注解通过这个扫描注解来完成这个包的扫描(给这个包下的所有的文件读取创建一个对象保存在我们的map集合当中)

package com.project1.AnnotationSpring;

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)
public @interface MyConfigurationScan {
    String name() default "";
    String[] packageName() default "";
}

  1. component注解,Service,Control注解
package com.project1.AnnotationSpring;

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)
public @interface MyComponent {
	String value() default "";
}

package com.project1.AnnotationSpring;

import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.lang.annotation.*;

/**
 * 当然了这个并没有实际上的应用这个地方也只是为了注解一下如果上面有这个注解的话
 */
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyService {
	@AliasFor(
			annotation = MyComponent.class,attribute = ""
	)
	String value() default "";
}
package com.project1.AnnotationSpring;

import org.springframework.core.annotation.AliasFor;

import java.lang.annotation.*;

/**
 * 当然了这个并没有实际上的应用这个地方也只是为了注解一下如果上面有这个注解的话
 */
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyControl {
	@AliasFor(
			annotation = MyComponent.class,attribute = ""
	)
	String value() default "";
}

  1. Autowired(注解这个地方我感觉还是不要去给他默认值的好就必须得给他写这个值才行)
package com.project1.AnnotationSpring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 简单的说这样也只是为了让这个文件的可读性更加的强大一点
 */
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAutowired {
	String value();
}

  1. 使用这个value注解来完成这个数据得注入
package com.project1.AnnotationSpring;

import org.springframework.beans.factory.annotation.Value;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 我们这个也是去模仿value注解的结构
 */
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValue {
	String value() ;
}

代替这个xml文件得配置类

package com.project1.AnnotationSpring;

/**
 * 通过这个类就可以完成这个包的扫描
 */
@MyConfiguration
@MyConfigurationScan(packageName = {"com.project1.Dao.impl","com.project1.Service"})
public class SpringConfig {
}

实现接口

package com.project1.Util;

public interface ApplicationContext {
	public Object getBean(String classPath);
	
	public <T> T getBean(String classPath, Class<T> clazz);
}

功能类(ClassPathXmlApplicationContext)

package com.project1.Util;

import com.project1.AnnotationSpring.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 当然了这个是基于全注解的开发模式就不去用这个配置文件了后面也会写这个配置文件版本的
 * @author 佚名
 * @version 1.0
 */
public class AnnotationConfigurationFactory implements ApplicationContext {
	static final Logger logger = LoggerFactory.getLogger(AnnotationConfigurationFactory.class);
	static Map<String, Object> objectMap = new HashMap<>();
	
	/**
	 * 需要传递一个类的文件路径我才可以去解析这个注解
	 * @param ConfigClass
	 */
	public AnnotationConfigurationFactory(Class<?> ConfigClass) {
		if (ConfigClass.isAnnotationPresent(MyConfiguration.class)) {
			MyConfigurationScan configurationScan = ConfigClass.getAnnotation(MyConfigurationScan.class);
			String[] packageNames = configurationScan.packageName();
			for (String packageName : packageNames) {
				String packageName1 = packageName.replaceAll("\\.", "/");
//				获取绝对路径这个一步十分的关键
				try {
					ClassLoader classLoader = ClassLoader.getSystemClassLoader();
					URL resource = classLoader.getResource(packageName1);
					String path = resource.getPath();
//					logger.info(resource.toString());
					File file = new File(path);
					File[] files = file.listFiles();
					for (File file1 : files) {
//						logger.info(file1.getName());//获取文件名
						String ClassName = file1.getName().split("\\.")[0];
//						logger.info(ClassName); 获取这个类的类名
						String ClassNamePath = packageName + "." + ClassName;
						Class<?> aClass = Class.forName(ClassNamePath);
//						logger.info(aClass.getName());   创建这个类
						Object o = aClass.newInstance();
//						logger.info(o.toString());  打印一下结果
						Annotation[] annotations = aClass.getAnnotations();
						for (Annotation annotation : annotations) {
//							logger.info(annotation.toString()); 可以读取到这个
							Class<? extends Annotation> annotationType = annotation.annotationType();
							String simpleName = annotationType.getSimpleName();
							switch (simpleName) {
								case "MyComponent":
									MyComponent annotation1 = (MyComponent) aClass.getAnnotation(MyComponent.class);
									SetMapObj(aClass, o, annotation1);
									break;
								case "MyService":
									MyService annotation2 = aClass.getAnnotation(MyService.class);
									SetMapObj((Class<?>) aClass, o, annotation2);
									break;
								case "MyControl":
									MyControl annotation3 = aClass.getAnnotation(MyControl.class);
									SetMapObj((Class<?>) aClass, o, annotation3);
									break;
							}
						}
						Field[] fields = aClass.getDeclaredFields();
						for (Field field : fields) {
//							注意这个地方要是两个注解都有一定要实现这个覆盖的功能
							boolean isValue = field.isAnnotationPresent(MyValue.class);
							boolean isAutowired = field.isAnnotationPresent(MyAutowired.class);
							if (isValue) {
								String simpleName = field.getType().getSimpleName();
								MyValue annotation = field.getAnnotation(MyValue.class);
								String value = annotation.value();
								SetFiled(o, field, simpleName, value);
							}
							if (isAutowired) {
								String simpleName = field.getType().getSimpleName();
								MyAutowired annotation = field.getAnnotation(MyAutowired.class);
								String value = annotation.value();
								SetFiled(o, field, simpleName, value);
							}
						}
					}
				} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
					e.printStackTrace();
					throw new RuntimeException("创建不了这个对象你的无参构造方法都没有我无法给你去创建对象");
				}
			}
//			logger.info(objectMap.toString()); 这个地方也只是打印一下日志的信息为了方便查看结果
		} else {
			throw new RuntimeException("你的配置类是不是不正确啊或者你这个上面是不是没有这个注解" + "MyConfiguration注解");
		}
	}
	
	/**
	 * 给这个字段进行赋值
	 * @param o          给哪一个对象赋值
	 * @param field      哪一个字段
	 * @param simpleName 简单的类名是什么
	 * @param value      最后要进行封装的内容是什么
	 * @throws IllegalAccessException
	 */
	private static void SetFiled(Object o, Field field, String simpleName, String value) throws IllegalAccessException {
		field.setAccessible(true);
		Object oj = value;
		switch (simpleName) {
			case "int", "Integer":
				oj = Integer.parseInt(value);
				break;
			case "byte", "Byte":
				oj = Byte.parseByte(value);
				break;
			case "boolean", "Boolean":
				oj = Boolean.parseBoolean(value);
				break;
			case "short", "Short":
				oj = Short.parseShort(value);
				break;
			case "double", "Double":
				oj = Double.parseDouble(value);
				break;
			case "float", "Float":
				oj = Float.parseFloat(value);
				break;
			case "char", "CharSet":
				oj = Character.valueOf(value.charAt(0));
				break;
			case "long", "Long":
				oj = Long.parseLong(value);
				break;
			case "String":
				oj = value;
				break;
			default:
				oj = objectMap.get(value);
				break;
		}
		field.set(o, oj);
	}
	
	private void SetMapObj(Class<?> aClass, Object o, MyControl annotation3) {
		String value = annotation3.value();
		String id = value;
		if (Objects.equals(value, "")) {
			id = getString(aClass);
		}
		objectMap.put(id, o);
	}
	
	/**
	 * 这个就是一个装换大小写的方法确实也是很简单
	 * @param aClass
	 * @return
	 */
	private static String getString(Class<?> aClass) {
		String id;
		char c = aClass.getSimpleName().charAt(0);
		char lowerCase = Character.toLowerCase(c);
		id = lowerCase + aClass.getSimpleName().substring(1);
		return id;
	}
	
	private void SetMapObj(Class<?> aClass, Object o, MyService annotation2) {
		String value = annotation2.value();
		String id = value;
		if (Objects.equals(value, "")) {
			id = getString(aClass);
		}
		objectMap.put(id, o);
	}
	
	private static void SetMapObj(Class<?> aClass, Object o, MyComponent annotation1) {
		String value = annotation1.value();
		String id = value;
		if (Objects.equals(value, "")) {
			id = getString(aClass);
		}
		objectMap.put(id, o);
	}
	
	/**
	 * 获取这个bean的方法
	 * @param classPath
	 * @return
	 */
	@Override
	@Deprecated
	public Object getBean(String classPath) {
		try {
			return objectMap.get(classPath);
		} catch (Exception e) {
			throw new RuntimeException("找不到这个类型请输入正确的bean的id");
		}
	}
	
	/**
	 * 通过这个可以直接获取到一个bean的实例对象
	 * @param classPath
	 * @param clazz
	 * @param <T>
	 * @return
	 */
	@Override
	public <T> T getBean(String classPath, Class<T> clazz) {
		Object bean = objectMap.get(classPath);
		if (clazz.isInstance(bean)) {
			return clazz.cast(bean);
		} else {
			throw new ClassCastException("Bean of type " + clazz.getName() + " not found for path: " + classPath);
		}
	}
}

结构图(client就是我们的测试类,其他得就是测试一下这个业务的代码)

结构图篇

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值