:::info 💡 初始化IOC容器+依赖注入+BeanPostProcessor机制+AOP ::: GitHub地址:https://github.com/1072344372/LHSpring
编写Spring容器,实现扫描包,得到bean的class对象 导包 创建对应文件,注意导入的是自定义的注解,
package asia.lhweb.spring.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 组件扫描
* 1 @Target(ElementType.TYPE):
* 指定ComponentScan注解可以修饰type类型
* 2 @Retention(RetentionPolicy.RUNTIME)
* 指定ComponentScan存活范围
* 3 表示ComponentScan可以传入value属性
* @author 罗汉
* @date 2023/07/17
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {
String value() default "";
}
Component、Controller、Repository、Service注解类似这里只展示Component注解
package asia.lhweb.spring.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 组件
*
* @author 罗汉
* @date 2023/07/23
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
//通过value可以给注入的bean指定id 名字
String value() default "";
}
package asia.lhweb.spring.component;
import asia.lhweb.spring.annotation.Service;
/**
* MonsterService是一个service
* 1 如果指定了那么在注入容器时以指定的为准
* 2 如果没有指定则使用类名首字母小写的名字
* @author 罗汉
* @date 2023/07/23
*/
@Service(value = "monsterService")//把MonsterService注入到我们自己的容器中
public class MonsterService {
}
package asia.lhweb.spring.ioc;
import asia.lhweb.spring.annotation.*;
import org.springframework.util.StringUtils;
import java.io.File;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;
/**
* lhspring应用程序上下文
*
* @author 罗汉
* @date 2023/07/23
*/
public class LHSpringApplicationContext {
private Class configClass;
// 基于注解
private final ConcurrentHashMap<String, Object> ioc = new ConcurrentHashMap<>();
public LHSpringApplicationContext(Class configClass) {
this.configClass = configClass;
System.out.println("配置的路径:this.configClass =" + configClass);
// 1得到注解
ComponentScan componentScan = (ComponentScan) this.configClass.getAnnotation(ComponentScan.class);
// 2通过componentScan得到要扫描的包
String path = componentScan.value();
System.out.println("要扫码的包为:path=" + path);
// 1 得到类加载器->APP 类加载器
ClassLoader classLoader = LHSpringApplicationContext.class.getClassLoader();
// 2 获取扫描包的url
path = path.replace(".", "/");
URL resource = classLoader.getResource(path);
System.out.println(resource);
File file = new File(resource.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File file1 : files) {
// System.out.println(file1);
String absolutePath = file1.getAbsolutePath();
// 只处理class文件
if (absolutePath.endsWith(".class")) {
// 绝对路径:---F:\JavaWorksparce\Spring\out\production\springTest\xyz\lhweb\spring\component\MyComponent.class
// xyz.lhweb.spring.component.MyComponent
// 1 获取类名
String className = absolutePath.substring(absolutePath.lastIndexOf("\\") + 1, absolutePath.indexOf(".class"));
// System.out.println(className);
// 2 获取类的完整路径
String classFullName = path.replace("/", ".") + "." + className;
System.out.println(classFullName);
// 3 判断该类是不是需要注入到容器中
try {
// 反射一个类对象
// 1 Class.forName 调用该类的静态方法
// 2 classLoader.loadClass 不会调用该类的静态方法
// 3 isAnnotationPresent判断该类是否有这个注解
Class<?> clazz = classLoader.loadClass(classFullName);
if (clazz.isAnnotationPresent(Service.class)
|| (clazz.isAnnotationPresent(Component.class))
|| (clazz.isAnnotationPresent(Controller.class))
|| (clazz.isAnnotationPresent(Repository.class))) {
if (clazz.isAnnotationPresent(Service.class)){
System.out.println("这是一个LHSpring bean="+clazz+" 类名="+className);
Service declaredAnnotation = clazz.getDeclaredAnnotation(Service.class);
String id = declaredAnnotation.value();
if (!StringUtils.isEmpty(id)){
className=id;//替换
}
}
if (clazz.isAnnotationPresent(Component.class)){
System.out.println("这是一个LHSpring bean="+clazz+" 类名="+className);
Component declaredAnnotation = clazz.getDeclaredAnnotation(Component.class);
String id = declaredAnnotation.value();
if (!StringUtils.isEmpty(id)){
className=id;//替换
}
}
if (clazz.isAnnotationPresent(Controller.class)){
System.out.println("这是一个LHSpring bean="+clazz+" 类名="+className);
Controller declaredAnnotation = clazz.getDeclaredAnnotation(Controller.class);
String id = declaredAnnotation.value();
if (!StringUtils.isEmpty(id)){
className=id;//替换
}
}
if (clazz.isAnnotationPresent(Repository.class)){
System.out.println("这是一个LHSpring bean="+clazz+" 类名="+className);
Repository declaredAnnotation = clazz.getDeclaredAnnotation(Repository.class);
String id = declaredAnnotation.value();
if (!StringUtils.isEmpty(id)){
className=id;//替换
}
}
}else {
System.out.println("这不是一个Spring bean="+clazz);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
}
//返回容器对象
public Object getBean(String name) {
return ioc.get(name);
}
}
package asia.lhweb.spring.ioc;
import asia.lhweb.spring.annotation.ComponentScan;
/**
* lhspring配置
* 类似beans.xml 容器配置文件
* @author 罗汉
* @date 2023/07/17
*/
@ComponentScan(value = "asia.lhweb.spring.component")
public class LHSpringConfig {
}
测试方法
import asia.lhweb.spring.ioc.LHSpringApplicationContext;
import asia.lhweb.spring.ioc.LHSpringConfig;
public class Text {
public static void main(String[] args) {
LHSpringApplicationContext ioc = new LHSpringApplicationContext(LHSpringConfig.class);
}
}
扫描将bean信息封装到BeanDefinition对象,并放入到Map
新增一个Scope注解
package asia.lhweb.spring.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 可以指定bean的作用范围【singleton,prototype】
*
* @author 罗汉
* @date 2023/07/23
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Scope {
//通过value可以指定是singleton还是prototype
String value() default "";
}
新建BeanDefiniton.java 用于封装/记录Bean的信息
package asia.lhweb.spring.ioc;
/**
* 用于封装/记录Bean的信息[1 scope 2 bean对应的class对象]
* @author :罗汉
* @date : 2023/7/23
*/
public class BeanDefiniton {
private String scope;
private Class clazz;
public BeanDefiniton() {
}
public BeanDefiniton(String scope, Class clazz) {
this.scope = scope;
this.clazz = clazz;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public Class getClazz() {
return clazz;
}
public void setClazz(Class clazz) {
this.clazz = clazz;
}
@Override
public String toString() {
return "BeanDefiniton{" +
"scope='" + scope + '\'' +
", clazz=" + clazz +
'}';
}
}
修改LHSpringApplicationContext
package asia.lhweb.spring.ioc;
import asia.lhweb.spring.annotation.*;
import org.springframework.util.StringUtils;
import java.io.File;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;
/**
* lhspring应用程序上下文
*
* @author 罗汉
* @date 2023/07/23
*/
public class LHSpringApplicationContext {
private Class configClass;
// 基于注解
private final ConcurrentHashMap<String, BeanDefiniton> beanDefinitonMap = new ConcurrentHashMap<>();//存放BeanDefiniton对象
private final ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();//存放单例对象
public LHSpringApplicationContext(Class configClass) {
beanDefiniton(configClass);
System.out.println("beanDefinitonMap="+beanDefinitonMap);
}
/**
* 完成对指定包的扫描,并且封装到BeanDefinition对象,再放入到Map中
*
* @param configClass 配置类
*/
private void beanDefiniton(Class configClass) {
this.configClass = configClass;
// System.out.println("配置的路径:this.configClass =" + configClass);
// 1得到注解
ComponentScan componentScan = (ComponentScan) this.configClass.getAnnotation(ComponentScan.class);
// 2通过componentScan得到要扫描的包
String path = componentScan.value();
// System.out.println("要扫码的包为:path=" + path);
// 1 得到类加载器->APP 类加载器
ClassLoader classLoader = LHSpringApplicationContext.class.getClassLoader();
// 2 获取扫描包的url
path = path.replace(".", "/");
URL resource = classLoader.getResource(path);
// System.out.println(resource);
File file = new File(resource.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File file1 : files) {
// System.out.println(file1);
String absolutePath = file1.getAbsolutePath();
// 只处理class文件
if (absolutePath.endsWith(".class")) {
// 绝对路径:---F:\JavaWorksparce\Spring\out\production\springTest\xyz\lhweb\spring\component\MyComponent.class
// xyz.lhweb.spring.component.MyComponent
// 1 获取类名
String className = absolutePath.substring(absolutePath.lastIndexOf("\\") + 1, absolutePath.indexOf(".class"));
// System.out.println(className);
// 2 获取类的完整路径
String classFullName = path.replace("/", ".") + "." + className;
System.out.println(classFullName);
// 3 判断该类是不是需要注入到容器中
try {
// 反射一个类对象
// 1 Class.forName 调用该类的静态方法
// 2 classLoader.loadClass 不会调用该类的静态方法
// 3 isAnnotationPresent判断该类是否有这个注解
Class<?> clazz = classLoader.loadClass(classFullName);
if (clazz.isAnnotationPresent(Service.class)
|| (clazz.isAnnotationPresent(Component.class))
|| (clazz.isAnnotationPresent(Controller.class))
|| (clazz.isAnnotationPresent(Repository.class))) {
if (clazz.isAnnotationPresent(Service.class)){
System.out.println("这是一个LHSpring bean="+clazz+" 类名="+className);
//将Bean的信息封装到BeanDefiniton中放入map
// 1 得到Service注解
Service declaredAnnotation = clazz.getDeclaredAnnotation(Service.class);
// 2 得到value值
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
if (clazz.isAnnotationPresent(Component.class)){
System.out.println("这是一个LHSpring bean="+clazz+" 类名="+className);
Component declaredAnnotation = clazz.getDeclaredAnnotation(Component.class);
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
if (clazz.isAnnotationPresent(Controller.class)){
System.out.println("这是一个LHSpring bean="+clazz+" 类名="+className);
Controller declaredAnnotation = clazz.getDeclaredAnnotation(Controller.class);
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
if (clazz.isAnnotationPresent(Repository.class)){
System.out.println("这是一个LHSpring bean="+clazz+" 类名="+className);
Repository declaredAnnotation = clazz.getDeclaredAnnotation(Repository.class);
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
}else {
System.out.println("这不是一个LHSpring bean="+clazz+" 类名="+className);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
}
/**
* 共同方法提取出来方法
*
* @param className 类名
* @param clazz clazz
* @param beanName bean名字
*/
private void method(String className, Class<?> clazz, String beanName) {
if ("".equals(beanName)){//如果为空
//首字母小写作为beanName
beanName = StringUtils.uncapitalize(className);//替换
}
// 3 放入map
BeanDefiniton beanDefiniton = new BeanDefiniton();
beanDefiniton.setClazz(clazz);
// 4 获取Scope值
if ( clazz.isAnnotationPresent(Scope.class)){
//如果配置了Scope
Scope scopedeclaredAnnotation = clazz.getDeclaredAnnotation(Scope.class);
beanDefiniton.setScope(scopedeclaredAnnotation.value());
}else {
//如果没有配置
beanDefiniton.setScope("singleton");
}
//放入到map中
beanDefinitonMap.put(beanName,beanDefiniton);
}
}
初始化bean单例池,并完成getBean方法,createBean方法 在LHSpringApplicationContext中创建一个得到bean的方法 修改方法 到此已经完成 写一个得到bean的方法
package asia.lhweb.spring.ioc;
import asia.lhweb.spring.annotation.*;
import org.springframework.util.StringUtils;
import java.io.File;
import java.net.URL;
import java.util.Enumeration;
import java.util.concurrent.ConcurrentHashMap;
/**
* lhspring应用程序上下文
*
* @author 罗汉
* @date 2023/07/23
*/
public class LHSpringApplicationContext {
private Class configClass;
// 基于注解
private final ConcurrentHashMap<String, BeanDefinition> beanDefinitonMap = new ConcurrentHashMap<>();// 存放BeanDefiniton对象
private final ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();// 存放单例对象
public LHSpringApplicationContext(Class configClass) {
//完成扫描
beanDefinitonByScan(configClass);
//通过beanDefinitonMap,初始化单例池 singletonObjects
System.out.println("beanDefinitonMap=" + beanDefinitonMap);
Enumeration<String> keys = beanDefinitonMap.keys();//kes指的是全部bean的名字
while (keys.hasMoreElements()){
//得到beanName
String beanName = keys.nextElement();
// System.out.println(beanName);
//通过BeanName 得到对应的beanDefinition对象
BeanDefinition beanDefinition = beanDefinitonMap.get(beanName);
// System.out.println(beanDefinition);
//判断该bean是singleton还是prototype
if ("singleton".equalsIgnoreCase(beanDefinition.getScope())){//是单例
//将该bean实例放入到singletonObjects
Object bean = createBean(beanDefinition);
singletonObjects.put(beanName,bean);
}
}
System.out.println(singletonObjects);
}
/**
* 完成对指定包的扫描,并且封装到BeanDefinition对象,再放入到Map中
*
* @param configClass 配置类
*/
public void beanDefinitonByScan(Class configClass) {
this.configClass = configClass;
// System.out.println("配置的路径:this.configClass =" + configClass);
// 1得到注解
ComponentScan componentScan = (ComponentScan) this.configClass.getAnnotation(ComponentScan.class);
// 2通过componentScan得到要扫描的包
String path = componentScan.value();
// System.out.println("要扫码的包为:path=" + path);
// 1 得到类加载器->APP 类加载器
ClassLoader classLoader = LHSpringApplicationContext.class.getClassLoader();
// 2 获取扫描包的url
path = path.replace(".", "/");
URL resource = classLoader.getResource(path);
// System.out.println(resource);
File file = new File(resource.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File file1 : files) {
// System.out.println(file1);
String absolutePath = file1.getAbsolutePath();
// 只处理class文件
if (absolutePath.endsWith(".class")) {
// 绝对路径:---F:\JavaWorksparce\Spring\out\production\springTest\xyz\lhweb\spring\component\MyComponent.class
// xyz.lhweb.spring.component.MyComponent
// 1 获取类名
String className = absolutePath.substring(absolutePath.lastIndexOf("\\") + 1, absolutePath.indexOf(".class"));
// System.out.println(className);
// 2 获取类的完整路径
String classFullName = path.replace("/", ".") + "." + className;
System.out.println(classFullName);
// 3 判断该类是不是需要注入到容器中
try {
// 反射一个类对象
// 1 Class.forName 调用该类的静态方法
// 2 classLoader.loadClass 不会调用该类的静态方法
// 3 isAnnotationPresent判断该类是否有这个注解
Class<?> clazz = classLoader.loadClass(classFullName);
if (clazz.isAnnotationPresent(Service.class)
|| (clazz.isAnnotationPresent(Component.class))
|| (clazz.isAnnotationPresent(Controller.class))
|| (clazz.isAnnotationPresent(Repository.class))) {
if (clazz.isAnnotationPresent(Service.class)) {
System.out.println("这是一个LHSpring bean=" + clazz + " 类名=" + className);
// 将Bean的信息封装到BeanDefiniton中放入map
// 1 得到Service注解
Service declaredAnnotation = clazz.getDeclaredAnnotation(Service.class);
// 2 得到value值
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
if (clazz.isAnnotationPresent(Component.class)) {
System.out.println("这是一个LHSpring bean=" + clazz + " 类名=" + className);
Component declaredAnnotation = clazz.getDeclaredAnnotation(Component.class);
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
if (clazz.isAnnotationPresent(Controller.class)) {
System.out.println("这是一个LHSpring bean=" + clazz + " 类名=" + className);
Controller declaredAnnotation = clazz.getDeclaredAnnotation(Controller.class);
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
if (clazz.isAnnotationPresent(Repository.class)) {
System.out.println("这是一个LHSpring bean=" + clazz + " 类名=" + className);
Repository declaredAnnotation = clazz.getDeclaredAnnotation(Repository.class);
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
} else {
System.out.println("这不是一个LHSpring bean=" + clazz + " 类名=" + className);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
}
/**
* 共同方法提取出来方法
*
* @param className 类名
* @param clazz clazz
* @param beanName bean名字
*/
public void method(String className, Class<?> clazz, String beanName) {
if ("".equals(beanName)) {// 如果为空
// 首字母小写作为beanName
beanName = StringUtils.uncapitalize(className);// 替换
}
// 3 放入map
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setClazz(clazz);
// 4 获取Scope值
if (clazz.isAnnotationPresent(Scope.class)) {
// 如果配置了Scope
Scope scopedeclaredAnnotation = clazz.getDeclaredAnnotation(Scope.class);
beanDefinition.setScope(scopedeclaredAnnotation.value());
} else {
// 如果没有配置
beanDefinition.setScope("singleton");
}
// 放入到map中
beanDefinitonMap.put(beanName, beanDefinition);
}
/**
* 创建bean
*
* @param beanDefinition bean定义
*/
private Object createBean(BeanDefinition beanDefinition) {
// 得到Bean的clazz对象
Class clazz = beanDefinition.getClazz();
try {
// 使用反射得到实例
Object instance = clazz.getDeclaredConstructor().newInstance();
return instance;
} catch (Exception e) {
e.printStackTrace();
}
// 如果反射创建对象失败
return null;
}
/**
* 得到bean
*
* @param beanName bean名字
* @return {@link Object}
*/
public Object getBean(String beanName) {
//判断 传入的beanName是否在beanDefinitonMap中存在
if (beanDefinitonMap.containsKey(beanName)){//存在
BeanDefinition beanDefinition = beanDefinitonMap.get(beanName);
//得到beanDefinition的scope,分别进行处理
if ("singleton".equalsIgnoreCase(beanDefinition.getScope())){
//说明是单例的,就直接从单例池获取
return singletonObjects.get(beanName);
}else {//不是单例就调用creatBean,反射一个对象
return createBean(beanDefinition);
}
}else {//不存在
//抛出个空指针异常
throw new NullPointerException("没有该bean");
}
}
}
结果 可以自行测试多次获取是否存在的bean名以及是否单例。
package asia.lhweb.spring.annotation;
import java.lang.annotation.*;
/**
* 自动装配注解
*
* @author 罗汉
* @date 2023/07/23
*/
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
//一定要找到一个匹配的找不到就会报错
// boolean required() default true;
}
package asia.lhweb.spring.ioc;
import asia.lhweb.spring.annotation.*;
import org.springframework.util.StringUtils;
import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Enumeration;
import java.util.concurrent.ConcurrentHashMap;
/**
* lhspring应用程序上下文
*
* @author 罗汉
* @date 2023/07/23
*/
public class LHSpringApplicationContext {
private Class configClass;
// 基于注解
private final ConcurrentHashMap<String, BeanDefinition> beanDefinitonMap = new ConcurrentHashMap<>();// 存放BeanDefiniton对象
private final ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();// 存放单例对象
public LHSpringApplicationContext(Class configClass) {
// 完成扫描
beanDefinitonByScan(configClass);
// 通过beanDefinitonMap,初始化单例池 singletonObjects
System.out.println("beanDefinitonMap=" + beanDefinitonMap);
Enumeration<String> keys = beanDefinitonMap.keys();// kes指的是全部bean的名字
while (keys.hasMoreElements()) {
// 得到beanName
String beanName = keys.nextElement();
// System.out.println(beanName);
// 通过BeanName 得到对应的beanDefinition对象
BeanDefinition beanDefinition = beanDefinitonMap.get(beanName);
// System.out.println(beanDefinition);
// 判断该bean是singleton还是prototype
if ("singleton".equalsIgnoreCase(beanDefinition.getScope())) {// 是单例
// 将该bean实例放入到singletonObjects
Object bean = createBean(beanDefinition);
singletonObjects.put(beanName, bean);
}
}
System.out.println(singletonObjects);
}
/**
* 完成对指定包的扫描,并且封装到BeanDefinition对象,再放入到Map中
*
* @param configClass 配置类
*/
public void beanDefinitonByScan(Class configClass) {
this.configClass = configClass;
// System.out.println("配置的路径:this.configClass =" + configClass);
// 1得到注解
ComponentScan componentScan = (ComponentScan) this.configClass.getAnnotation(ComponentScan.class);
// 2通过componentScan得到要扫描的包
String path = componentScan.value();
// System.out.println("要扫码的包为:path=" + path);
// 1 得到类加载器->APP 类加载器
ClassLoader classLoader = LHSpringApplicationContext.class.getClassLoader();
// 2 获取扫描包的url
path = path.replace(".", "/");
URL resource = classLoader.getResource(path);
// System.out.println(resource);
File file = new File(resource.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File file1 : files) {
// System.out.println(file1);
String absolutePath = file1.getAbsolutePath();
// 只处理class文件
if (absolutePath.endsWith(".class")) {
// 绝对路径:---F:\JavaWorksparce\Spring\out\production\springTest\xyz\lhweb\spring\component\MyComponent.class
// xyz.lhweb.spring.component.MyComponent
// 1 获取类名
String className = absolutePath.substring(absolutePath.lastIndexOf("\\") + 1, absolutePath.indexOf(".class"));
// System.out.println(className);
// 2 获取类的完整路径
String classFullName = path.replace("/", ".") + "." + className;
System.out.println(classFullName);
// 3 判断该类是不是需要注入到容器中
try {
// 反射一个类对象
// 1 Class.forName 调用该类的静态方法
// 2 classLoader.loadClass 不会调用该类的静态方法
// 3 isAnnotationPresent判断该类是否有这个注解
Class<?> clazz = classLoader.loadClass(classFullName);
if (clazz.isAnnotationPresent(Service.class) || (clazz.isAnnotationPresent(Component.class)) || (clazz.isAnnotationPresent(Controller.class)) || (clazz.isAnnotationPresent(Repository.class))) {
if (clazz.isAnnotationPresent(Service.class)) {
System.out.println("这是一个LHSpring bean=" + clazz + " 类名=" + className);
// 将Bean的信息封装到BeanDefiniton中放入map
// 1 得到Service注解
Service declaredAnnotation = clazz.getDeclaredAnnotation(Service.class);
// 2 得到value值
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
if (clazz.isAnnotationPresent(Component.class)) {
System.out.println("这是一个LHSpring bean=" + clazz + " 类名=" + className);
Component declaredAnnotation = clazz.getDeclaredAnnotation(Component.class);
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
if (clazz.isAnnotationPresent(Controller.class)) {
System.out.println("这是一个LHSpring bean=" + clazz + " 类名=" + className);
Controller declaredAnnotation = clazz.getDeclaredAnnotation(Controller.class);
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
if (clazz.isAnnotationPresent(Repository.class)) {
System.out.println("这是一个LHSpring bean=" + clazz + " 类名=" + className);
Repository declaredAnnotation = clazz.getDeclaredAnnotation(Repository.class);
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
} else {
System.out.println("这不是一个LHSpring bean=" + clazz + " 类名=" + className);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
}
/**
* 共同方法提取出来方法
*
* @param className 类名
* @param clazz clazz
* @param beanName bean名字
*/
public void method(String className, Class<?> clazz, String beanName) {
if ("".equals(beanName)) {// 如果为空
// 首字母小写作为beanName
beanName = StringUtils.uncapitalize(className);// 替换
}
// 3 放入map
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setClazz(clazz);
// 4 获取Scope值
if (clazz.isAnnotationPresent(Scope.class)) {
// 如果配置了Scope
Scope scopedeclaredAnnotation = clazz.getDeclaredAnnotation(Scope.class);
beanDefinition.setScope(scopedeclaredAnnotation.value());
} else {
// 如果没有配置
beanDefinition.setScope("singleton");
}
// 放入到map中
beanDefinitonMap.put(beanName, beanDefinition);
}
/**
* 创建bean
*
* @param beanDefinition bean定义
*/
private Object createBean(BeanDefinition beanDefinition) {
// 得到Bean的clazz对象
Class clazz = beanDefinition.getClazz();
try {
// 使用反射得到实例
Object instance = clazz.getDeclaredConstructor().newInstance();
// 加入依赖注入的业务逻辑
// 1 遍历当前要创建的对象的所有字段
for (Field declaredField : clazz.getDeclaredFields()) {
// 2 判断这个字段是否有Autowired注解修饰
if (declaredField.isAnnotationPresent(Autowired.class)) {
// 3得到字段的名字
String name = declaredField.getName();
// 4 通过getBean方法来获取要组装的对象
Object bean = getBean(name);
// 5 进行组装
// 因为属性是私有的不能反射 所以需要爆破
declaredField.setAccessible(true);
declaredField.set(instance, bean);// 第一个是需要组装的对象 第二个参数是你要组装的东西
}
}
return instance;
} catch (Exception e) {
e.printStackTrace();
}
// 如果反射创建对象失败
return null;
}
/**
* 得到bean
*
* @param beanName bean名字
* @return {@link Object}
*/
public Object getBean(String beanName) {
// 判断 传入的beanName是否在beanDefinitonMap中存在
if (beanDefinitonMap.containsKey(beanName)) {// 存在
BeanDefinition beanDefinition = beanDefinitonMap.get(beanName);
// 得到beanDefinition的scope,分别进行处理
if ("singleton".equalsIgnoreCase(beanDefinition.getScope())) {
// 说明是单例的,就直接从单例池获取
return singletonObjects.get(beanName);
} else {// 不是单例就调用creatBean,反射一个对象
return createBean(beanDefinition);
}
} else {// 不存在
// 抛出个空指针异常
throw new NullPointerException("没有该bean");
}
}
}
根据原生spring定义一个接口 搞定初始化方法 模仿spring新建一个接口BeanPostProcessor.java
package asia.lhweb.spring.processor;
import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;
/**
* 后置处理程序
* 1 参考原生spring容器定义的一个接口
* 2 该接口有2个方法
* 3 这2个方法会对spring容器的全部bean生效(切面编程的概念)
* @author 罗汉
* @date 2023/07/24
*/
public interface BeanPostProcessor {
/**
* 在初始化方法前调用
*
* @param bean 豆
* @param beanName bean名字
* @return {@link Object}
*/
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName){
return bean;
}
/**
* 发布过程初始化后调用
*
* @param bean 豆
* @param beanName bean名字
* @return {@link Object}
*/
default Object postProcessAfterInitialization(Object bean, String beanName){
return bean;
}
}
写一个自己的后置处理器(目前还是普通的bean)
package asia.lhweb.spring.component;
import asia.lhweb.spring.annotation.Component;
import asia.lhweb.spring.processor.BeanPostProcessor;
/**
* lhbean后置处理程序
* 可以写里面的方法
*
* 在spring容器中仍然把后置处理器当成一个bean对待
*
* @author 罗汉
* @date 2023/07/24
*/
@Component
public class LHBeanPostProcessor implements BeanPostProcessor {
/**
* 在初始化方法前调用
*
* @param bean 豆
* @param beanName bean名字
* @return {@link Object}
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("后置处理器LHBeanPostProcessor 的before调用 bean的类型="+
bean.getClass()+"bean的名字="+beanName);
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
/**
* 发布过程初始化后调用
*
* @param bean 豆
* @param beanName bean名字
* @return {@link Object}
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("后置处理器LHBeanPostProcessor 的after调用 bean的类型="+
bean.getClass()+"bean的名字="+beanName);
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
修改beanDefinitonByScan方法 修改createBean方法 新建一个car测试
package asia.lhweb.spring.component;
import asia.lhweb.spring.annotation.Component;
import asia.lhweb.spring.processor.InitializingBean;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
/**
* @author :罗汉
* @date : 2023/7/24
*/
@Component
public class car implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("car的初始化方法");
}
}
package asia.lhweb.spring.ioc;
import asia.lhweb.spring.annotation.*;
import asia.lhweb.spring.processor.BeanPostProcessor;
import asia.lhweb.spring.processor.InitializingBean;
import org.springframework.util.StringUtils;
import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* lhspring应用程序上下文
*
* @author 罗汉
* @date 2023/07/23
*/
public class LHSpringApplicationContext {
private Class configClass;
// 基于注解
private final ConcurrentHashMap<String, BeanDefinition> beanDefinitonMap = new ConcurrentHashMap<>();// 存放BeanDefiniton对象
private final ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();// 存放单例对象
//定义一个属性 用来存放后置处理器
private List<BeanPostProcessor> beanPostProcessorList=new ArrayList<BeanPostProcessor>();
public LHSpringApplicationContext(Class configClass) {
// 完成扫描
beanDefinitonByScan(configClass);
// 通过beanDefinitonMap,初始化单例池 singletonObjects
System.out.println("beanDefinitonMap=" + beanDefinitonMap);
Enumeration<String> keys = beanDefinitonMap.keys();// kes指的是全部bean的名字
while (keys.hasMoreElements()) {
// 得到beanName
String beanName = keys.nextElement();
// System.out.println(beanName);
// 通过BeanName 得到对应的beanDefinition对象
BeanDefinition beanDefinition = beanDefinitonMap.get(beanName);
// System.out.println(beanDefinition);
// 判断该bean是singleton还是prototype
if ("singleton".equalsIgnoreCase(beanDefinition.getScope())) {// 是单例
// 将该bean实例放入到singletonObjects
Object bean = createBean(beanName,beanDefinition);
singletonObjects.put(beanName, bean);
}
}
System.out.println(singletonObjects);
}
/**
* 完成对指定包的扫描,并且封装到BeanDefinition对象,再放入到Map中
*
* @param configClass 配置类
*/
public void beanDefinitonByScan(Class configClass) {
this.configClass = configClass;
// System.out.println("配置的路径:this.configClass =" + configClass);
// 1得到注解
ComponentScan componentScan = (ComponentScan) this.configClass.getAnnotation(ComponentScan.class);
// 2通过componentScan得到要扫描的包
String path = componentScan.value();
// System.out.println("要扫码的包为:path=" + path);
// 1 得到类加载器->APP 类加载器
ClassLoader classLoader = LHSpringApplicationContext.class.getClassLoader();
// 2 获取扫描包的url
path = path.replace(".", "/");
URL resource = classLoader.getResource(path);
// System.out.println(resource);
File file = new File(resource.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File file1 : files) {
// System.out.println(file1);
String absolutePath = file1.getAbsolutePath();
// 只处理class文件
if (absolutePath.endsWith(".class")) {
// 绝对路径:---F:\JavaWorksparce\Spring\out\production\springTest\xyz\lhweb\spring\component\MyComponent.class
// xyz.lhweb.spring.component.MyComponent
// 1 获取类名
String className = absolutePath.substring(absolutePath.lastIndexOf("\\") + 1, absolutePath.indexOf(".class"));
// System.out.println(className);
// 2 获取类的完整路径
String classFullName = path.replace("/", ".") + "." + className;
System.out.println(classFullName);
// 3 判断该类是不是需要注入到容器中
try {
// 反射一个类对象
// 1 Class.forName 调用该类的静态方法
// 2 classLoader.loadClass 不会调用该类的静态方法
// 3 isAnnotationPresent判断该类是否有这个注解
Class<?> clazz = classLoader.loadClass(classFullName);
if (clazz.isAnnotationPresent(Service.class) || (clazz.isAnnotationPresent(Component.class)) || (clazz.isAnnotationPresent(Controller.class)) || (clazz.isAnnotationPresent(Repository.class))) {
if (clazz.isAnnotationPresent(Service.class)) {
System.out.println("这是一个LHSpring bean=" + clazz + " 类名=" + className);
// 将Bean的信息封装到BeanDefiniton中放入map
// 1 得到Service注解
Service declaredAnnotation = clazz.getDeclaredAnnotation(Service.class);
// 2 得到value值
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
if (clazz.isAnnotationPresent(Component.class)) {
//为了方便 将后置处理器放到list集合中
//1 如果发现是一个后置处理器
//2 在原生spring容器中,对后置处理器还是走的getBean,createBean
//但是需要再单例池中加对应的逻辑,这里只是为了体验 所以直接放入到list集合中
//判断是否实现是后置处理器
//这里不能使用 instanceof 来判断 原因:clazz不是一个实例对象,而是一个类对象
if (BeanPostProcessor.class.isAssignableFrom(clazz)){
BeanPostProcessor instance = (BeanPostProcessor) clazz.newInstance();
//放入到集合中
beanPostProcessorList.add(instance);
continue;
}
System.out.println("这是一个LHSpring bean=" + clazz + " 类名=" + className);
Component declaredAnnotation = clazz.getDeclaredAnnotation(Component.class);
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
if (clazz.isAnnotationPresent(Controller.class)) {
System.out.println("这是一个LHSpring bean=" + clazz + " 类名=" + className);
Controller declaredAnnotation = clazz.getDeclaredAnnotation(Controller.class);
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
if (clazz.isAnnotationPresent(Repository.class)) {
System.out.println("这是一个LHSpring bean=" + clazz + " 类名=" + className);
Repository declaredAnnotation = clazz.getDeclaredAnnotation(Repository.class);
String beanName = declaredAnnotation.value();
method(className, clazz, beanName);
}
} else {
System.out.println("这不是一个LHSpring bean=" + clazz + " 类名=" + className);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
}
/**
* 共同方法提取出来方法
*
* @param className 类名
* @param clazz clazz
* @param beanName bean名字
*/
public void method(String className, Class<?> clazz, String beanName) {
if ("".equals(beanName)) {// 如果为空
// 首字母小写作为beanName
beanName = StringUtils.uncapitalize(className);// 替换
}
// 3 放入map
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setClazz(clazz);
// 4 获取Scope值
if (clazz.isAnnotationPresent(Scope.class)) {
// 如果配置了Scope
Scope scopedeclaredAnnotation = clazz.getDeclaredAnnotation(Scope.class);
beanDefinition.setScope(scopedeclaredAnnotation.value());
} else {
// 如果没有配置
beanDefinition.setScope("singleton");
}
// 放入到map中
beanDefinitonMap.put(beanName, beanDefinition);
}
/**
* 创建bean
*
* @param beanDefinition bean定义
*/
private Object createBean(String beanName,BeanDefinition beanDefinition) {
// 得到Bean的clazz对象
Class clazz = beanDefinition.getClazz();
try {
// 使用反射得到实例
Object instance = clazz.getDeclaredConstructor().newInstance();
// 加入依赖注入的业务逻辑
// 1 遍历当前要创建的对象的所有字段
for (Field declaredField : clazz.getDeclaredFields()) {
// 2 判断这个字段是否有Autowired注解修饰
if (declaredField.isAnnotationPresent(Autowired.class)) {
// 3得到字段的名字
String name = declaredField.getName();
// 4 通过getBean方法来获取要组装的对象
Object bean = getBean(name);
// 5 进行组装
// 因为属性是私有的不能反射 所以需要爆破
declaredField.setAccessible(true);
declaredField.set(instance, bean);// 第一个是需要组装的对象 第二个参数是你要组装的东西
}
}
System.out.println();
System.out.println("=========创建好bean====="+instance);
//在bean的初始化方法前调用后置处理器方法
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
//在后置处理器的before方法前可以对Bean进行处理 , 然后再返回处理后的bean
//相当于做了一个前置处理
Object current=
beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
if (current!=null){
instance=current;
}
}
//这里判断是执行bean的初始化方法
// 1 判断当前创建的bean对象是否实现了InitializingBean接口
if (instance instanceof InitializingBean){
// 2 将instance转成InitializingBean类型
try {
((InitializingBean)instance).afterPropertiesSet();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//在bean的初始化方法后调用后置处理器方法
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
//在后置处理器的after方法前可以对Bean进行处理 , 然后再返回处理后的bean
//相当于做了后置处理
Object current=
beanPostProcessor.postProcessAfterInitialization(instance, beanName);
if (current!=null){
instance=current;
}
}
return instance;
} catch (Exception e) {
e.printStackTrace();
}
// 如果反射创建对象失败
return null;
}
/**
* 得到bean
*
* @param beanName bean名字
* @return {@link Object}
*/
public Object getBean(String beanName) {
// 判断 传入的beanName是否在beanDefinitonMap中存在
if (beanDefinitonMap.containsKey(beanName)) {// 存在
BeanDefinition beanDefinition = beanDefinitonMap.get(beanName);
// 得到beanDefinition的scope,分别进行处理
if ("singleton".equalsIgnoreCase(beanDefinition.getScope())) {
// 说明是单例的,就直接从单例池获取
return singletonObjects.get(beanName);
} else {// 不是单例就调用creatBean,反射一个对象
return createBean(beanName,beanDefinition);
}
} else {// 不存在
// 抛出个空指针异常
throw new NullPointerException("没有该bean");
}
}
}
先死后活,先实现一个简单的切面类 新建一个接口和实现类
package asia.lhweb.spring.component;
/**
* @author :罗汉
* @date : 2023/7/24
*/
public interface SmartAnimalable {
float getSum(float x,float y);
float getSub(float x,float y);
}
package asia.lhweb.spring.component;
import asia.lhweb.spring.annotation.Component;
/**
* @author :罗汉
* @date : 2023/7/24
*/
@Component(value = "smartDog")
public class SmartDog implements SmartAnimalable{
@Override
public float getSum(float x, float y) {
System.out.println("SmartDog getSum");
return x+y;
}
@Override
public float getSub(float x, float y) {
System.out.println("SmartDog getSub");
return x*y;
}
}
package asia.lhweb.spring.component;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;
/**
* 切面类
*
*
* @author 罗汉
* @date 2023/07/24
*/
public class SmartAnimalAspectj {
public SmartAnimalAspectj() {
}
public static void showBeginLog(){
System.out.println("前置类");
}
public static void showSuccessLog(){
System.out.println("返回通知");
}
}
AOP可以使用注解会更灵活,暂时先做到这里 有机会我再更新