Los dos artículos anteriores introdujeron la reflexión y la anotación basadas en Java. Los principios básicos de la implementación de contenedores de IOC de Spring utilizan la reflexión y la anotación (configuración en forma de anotaciones). Después de leer la reflexión y la anotación, los estudiantes pueden volver a leer este blog. Una sólida comprensión de reflexión y anotación
Reflexión: el alma del diseño de frameworks Java
Análisis de pensamiento
Hay tres notas:
- Componente: el frijol que se va a cargar
- ComponentScan: el paquete en el que se encuentra el bean
- Valor: Asignar valores a algunas propiedades del bean.
Análisis de proceso:
Código:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
}
/**
* @author 四五又十
* @create 2021/2/1 20:27
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {
String[] value();
}
/**
* @author 四五又十
* @create 2021/2/1 20:27
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Value {
String value();
}
Clase de código central
package cn.noteblogs.reflect;
import cn.noteblogs.Application;
import cn.noteblogs.annotation.Component;
import cn.noteblogs.annotation.ComponentScan;
import cn.noteblogs.annotation.Value;
import java.io.File;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class AnnotationConfigApplicationContext {
private String path;
private Map<Class, Object> beanFactory = new HashMap<>();
public AnnotationConfigApplicationContext() {
this.initBeanByAnnotation();
}
public Object getBean(Class clazz){
return beanFactory.get(clazz);
}
public void initBeanByAnnotation() {
path = AnnotationConfigApplicationContext.class.getClassLoader().getResource("").getFile();
// /E:/IdeaProjecty/SpringIOCTest/out/production/SpringIOCTest/
//System.out.println(path);
Class<Application> clazz = Application.class;
ComponentScan componentScan = clazz.getAnnotation(ComponentScan.class);
if(componentScan != null){
String[] value = componentScan.value();
for (String componentPath : value) {
if(componentPath != null && componentPath.length() > 0){
// cn.noteblogs.bean
//System.out.println(componentPath);
loadClassInDefinedDir(componentPath);
}
}
}
}
private void loadClassInDefinedDir(String componentPath) {
//cn.noteblogs.bean 需要将这个路径变为 /E:/IdeaProjecty/SpringIOCTest/out/production/SpringIOCTest/cn/noteblogs/bean
componentPath = componentPath.replaceAll("\\.", "/");
String fileDir = path + componentPath;
///E:/IdeaProjecty/SpringIOCTest/out/production/SpringIOCTest/cn/noteblogs/bean
//System.out.println(classPath);
//加载这个文件夹下的所有class类,并判断是否有@Component
findClassByFile(new File(fileDir));
}
private void findClassByFile(File fileDir) {
if(fileDir.isDirectory()){
File[] files = fileDir.listFiles();
if(files == null || files.length == 0) return;
for (File file : files) {
if(file.isDirectory()){
findClassByFile(file);
}else{
loadClassByAnnotation(file);
}
}
}
}
private void loadClassByAnnotation(File file) {
// /E:/IdeaProjecty/SpringIOCTest/out/production/SpringIOCTest/cn/noteblogs/bean/user.class
// 变为cn.noteblogs.bean.user
String classPath = file.getAbsolutePath().substring(path.length() - 1).replaceAll("\\\\", "\\.");
//cn.noteblogs.bean.user.class
// System.out.println(classPath);
if(classPath != null && classPath.length() > 0 && classPath.contains(".class")){
classPath = classPath.replaceAll("\\.class", "");
//System.out.println(classPath);
Class<?> clazz = null;
try {
clazz = Class.forName(classPath);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Component component = clazz.getAnnotation(Component.class);
if(component != null){
Object instance = null;
try {
instance = clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Class<?>[] interfaces = clazz.getInterfaces();
// Map<UserDao.class, UserDaoImpl>
if(interfaces != null && interfaces.length > 0){
beanFactory.put(interfaces[0], instance);
}else{
beanFactory.put(clazz, instance);
}
//获取该对象的所有域,然后判断是否有value注解进行赋值
Field[] declaredFields = clazz.getDeclaredFields();
if(declaredFields != null && declaredFields.length > 0){
for (Field f : declaredFields) {
Value annotation = f.getAnnotation(Value.class);
if(annotation != null){
String value = annotation.value();
f.setAccessible(true);
try {
f.set(instance, value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
}
}
}
@ComponentScan({
"cn.noteblogs.bean","cn.noteblogs.dao"})
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
User user = (User)ac.getBean(User.class);
System.out.println(user);
UserDao dao = (UserDao)ac.getBean(UserDao.class);
System.out.println(dao.getClass());
}
}
Estructura general del proyecto