前の2つの記事では、Javaベースのリフレクションとアノテーションを紹介しました。SpringのIOCコンテナー実装のコア原則は、リフレクションとアノテーション(アノテーション形式の構成)を使用します。リフレクションとアノテーションを読んだ後、学生はこのブログをもう一度読むことができます。反射と注釈
思考分析
3つのメモがあります:
- コンポーネント:ロードされるBean
- ComponentScan:Beanが配置されているパッケージ
- 値:Beanのいくつかのプロパティに値を割り当てます
プロセス分析:
コード:
@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();
}
コアコードクラス
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());
}
}
プロジェクト全体の構造