Default Changelist

This commit is contained in:
19611
2025-10-02 15:20:20 +08:00
commit 61c0476f9d
42 changed files with 630 additions and 0 deletions

8
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

13
.idea/compiler.xml generated Normal file
View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="zhouyu-spring-vip" />
</profile>
</annotationProcessing>
</component>
</project>

20
.idea/jarRepositories.xml generated Normal file
View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>

15
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
<option name="workspaceImportForciblyTurnedOn" value="true" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

16
pom.xml Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>zhouyu-spring-vip</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>

View File

@@ -0,0 +1,13 @@
package com.spring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
}

View File

@@ -0,0 +1,35 @@
package com.spring;
/**
* @author 周瑜
*/
public class BeanDefinition {
private Class type;
private String scope;
private boolean isLazy;
public Class getType() {
return type;
}
public void setType(Class type) {
this.type = type;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public boolean isLazy() {
return isLazy;
}
public void setLazy(boolean lazy) {
isLazy = lazy;
}
}

View File

@@ -0,0 +1,6 @@
package com.spring;
public interface BeanNameAware {
void setBeanName(String name);
}

View File

@@ -0,0 +1,12 @@
package com.spring;
public interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}

View File

@@ -0,0 +1,13 @@
package com.spring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
String value() default "";
}

View File

@@ -0,0 +1,13 @@
package com.spring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
String value() default "";
}

View File

@@ -0,0 +1,5 @@
package com.spring;
public interface InitializingBean {
void afterPropertiesSet();
}

View File

@@ -0,0 +1,69 @@
package com.spring;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class MyClassLoader extends ClassLoader {
// 外部类文件的根路径(可修改为你的实际路径,如"D:/my-external-classes/"
private final String externalClassRootPath;
// 构造方法:传入外部类的根路径
public MyClassLoader(String externalClassRootPath) {
// 调用父类构造(此处用系统类加载器作为父加载器,符合双亲委派模型)
super(ClassLoader.getSystemClassLoader());
// 确保路径以"/"或"\"结尾,避免拼接错误
this.externalClassRootPath = externalClassRootPath.endsWith("/")
? externalClassRootPath
: externalClassRootPath + "/";
}
/**
* 核心方法:根据类的全限定名找到并加载类
* @param className 类的全限定名(如"com.example.OuterClass"
* @return 加载后的Class对象
* @throws ClassNotFoundException 类未找到时抛出
*/
@Override
protected Class<?> findClass(String className) throws ClassNotFoundException {
try {
// 1. 将全限定名转换为文件路径(如"com.example.OuterClass" → "com/example/OuterClass.class"
String classFilePath = className.replace(".", "/") + ".class";
// 2. 拼接外部类的完整路径(根路径 + 类路径)
String fullClassPath = externalClassRootPath + classFilePath;
// 3. 读取.class文件的字节码二进制数据
byte[] classBytes = readClassBytes(fullClassPath);
// 4. 将字节码转换为Class对象defineClass是父类方法不可重写
// 参数说明className类名、classBytes字节码数组、0起始索引、classBytes.length长度
return defineClass(className, classBytes, 0, classBytes.length);
} catch (IOException e) {
// 若读取失败抛出ClassNotFoundException符合ClassLoader规范
throw new ClassNotFoundException("未找到外部类:" + className, e);
}
}
/**
* 辅助方法:读取指定路径下的.class文件返回字节数组
* @param fullClassPath .class文件的完整路径如"D:/external-classes/com/example/OuterClass.class"
* @return .class文件的字节数组
* @throws IOException 读取文件失败时抛出
*/
private byte[] readClassBytes(String fullClassPath) throws IOException {
// 用 ByteArrayOutputStream 暂存字节数据
try (InputStream inputStream = new FileInputStream(fullClassPath);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
byte[] buffer = new byte[1024]; // 缓冲区,提高读取效率
int bytesRead;
// 循环读取文件内容到缓冲区,再写入输出流
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
// 将输出流转换为字节数组(即.class文件的二进制数据
return outputStream.toByteArray();
}
}
}

View File

@@ -0,0 +1,13 @@
package com.spring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
String value() default "";
}

View File

@@ -0,0 +1,185 @@
package com.spring;
import com.zhouyu.service.ZhouyuBeanPostProcessor;
import java.beans.Introspector;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author 周瑜
*/
public class ZhouyuApplicationContext {
private Class configClass;
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
private Map<String, Object> singletonObjects = new HashMap<>();
private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
public ZhouyuApplicationContext(Class configClass) {
this.configClass = configClass;
// 扫描
scan(configClass);
for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
String beanName = entry.getKey();
BeanDefinition beanDefinition = entry.getValue();
if (beanDefinition.getScope().equals("singleton")) {
Object bean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, bean);
}
}
}
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Class clazz = beanDefinition.getType();
Object instance = null;
try {
instance = clazz.getConstructor().newInstance();
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
field.setAccessible(true);
field.set(instance, getBean(field.getName()));
}
}
if (instance instanceof BeanNameAware) {
((BeanNameAware)instance).setBeanName(beanName);
}
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
}
if (instance instanceof InitializingBean) {
((InitializingBean)instance).afterPropertiesSet();
}
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return instance;
}
public Object getBean(String beanName) {
if (!beanDefinitionMap.containsKey(beanName)) {
throw new NullPointerException();
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("singleton")) {
Object singletonBean = singletonObjects.get(beanName);
if (singletonBean == null) {
singletonBean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, singletonBean);
}
return singletonBean;
} else {
// 原型
Object prototypeBean = createBean(beanName, beanDefinition);
return prototypeBean;
}
}
private void scan(Class configClass) {
if (configClass.isAnnotationPresent(ComponentScan.class)) {
ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
String path = componentScanAnnotation.value();
path = path.replace(".", "/"); // com/zhouyu/service
ClassLoader classLoader = ZhouyuApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
if (file.isDirectory()) {
for (File f : file.listFiles()) {
String absolutePath = f.getAbsolutePath();
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
absolutePath = absolutePath.replace("\\", ".");
try {
Class<?> clazz = classLoader.loadClass(absolutePath);
if (clazz.isAnnotationPresent(Component.class)) {
if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();
beanPostProcessorList.add(instance);
}
Component componentAnnotation = clazz.getAnnotation(Component.class);
String beanName = componentAnnotation.value();
if ("".equals(beanName)) {
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(clazz);
if (clazz.isAnnotationPresent(Scope.class)) {
Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
String value = scopeAnnotation.value();
beanDefinition.setScope(value);
} else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
package com.zhouyu;
import com.spring.ComponentScan;
/**
* @author 周瑜
*/
@ComponentScan("com.zhouyu.service")
public class AppConfig {
}

View File

@@ -0,0 +1,51 @@
package com.zhouyu;
import com.spring.MyClassLoader;
import com.spring.ZhouyuApplicationContext;
import com.zhouyu.service.UserInterface;
import com.zhouyu.service.UserService;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* @author 周瑜
*/
public class Test {
public static void main(String[] args) {
// 扫描--->创建单例Bean BeanDefinition BeanPostPRocess
ZhouyuApplicationContext applicationContext = new ZhouyuApplicationContext(AppConfig.class);
UserInterface userService = (UserInterface) applicationContext.getBean("userService");
userService.test();
// 自定义类加载器
extracted(args);
}
private static void extracted(String[] args) {
MyClassLoader myClassLoader = new MyClassLoader("D:\\WorkSpace\\sheep\\learn\\target\\classes");
try {
Class<?> clazz = myClassLoader.loadClass("org.sheep.Find");
Object obj = clazz.getConstructor().newInstance();
System.out.println(obj.toString());
Method method = clazz.getMethod("main",String[].class);
method.invoke(obj, new Object[]{args});
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,15 @@
package com.zhouyu.service;
import com.spring.Component;
/**
* @author 周瑜
*/
@Component
public class OrderService {
public void test() {
System.out.println("test");
}
}

View File

@@ -0,0 +1,6 @@
package com.zhouyu.service;
public interface UserInterface {
public void test();
}

View File

@@ -0,0 +1,28 @@
package com.zhouyu.service;
import com.spring.*;
/**
* @author 周瑜
*/
@Component
public class UserService implements UserInterface, BeanNameAware {
@Autowired
private OrderService orderService;
@ZhouyuValue("xxx")
private String test;
private String beanName;
@Override
public void setBeanName(String name) {
this.beanName = name;
}
public void test() {
System.out.println(beanName);
}
}

View File

@@ -0,0 +1,36 @@
package com.zhouyu.service;
import com.spring.BeanPostProcessor;
import com.spring.Component;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author 周瑜
*/
@Component
public class ZhouyuBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (beanName.equals("userService")) {
Object proxyInstance = Proxy.newProxyInstance(ZhouyuBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 切面
System.out.println("切面逻辑");
return method.invoke(bean, args);
}
});
return proxyInstance;
}
// bean
return bean;
}
}

View File

@@ -0,0 +1,13 @@
package com.zhouyu.service;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ZhouyuValue {
String value() default "";
}

View File

@@ -0,0 +1,34 @@
package com.zhouyu.service;
import com.spring.BeanPostProcessor;
import com.spring.Component;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author 周瑜
*/
@Component
public class ZhouyuValueBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
for (Field field : bean.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(ZhouyuValue.class)) {
field.setAccessible(true);
try {
field.set(bean, field.getAnnotation(ZhouyuValue.class).value());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
// bean
return bean;
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.