准备:创建一个空的maven项目
//IOC的加载(启动容器)
ApplicationContext applicationContext = new ApplicationContext(AppConfig.class);
1.根据传入的配置类拿到ComponentScan类信息
2.获取扫描路径 包 com.tes.service--->需转为com/tes/service
3.根据获取到的扫描路径获取在路径包下所有类的信息
4.判断所扫描到的类上是否有Component注解,有的话表示当前类是一个Bean对象
......
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
String value() default "";//默认值为空,可以不写
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
// String value() default "";//扫描路径默认值为空
String value();
}
@ComponentScan("com.tes.service")
public class AppConfig {
}
import com.spring.Component;
import com.spring.Scope;
@Component("userService")
public class UserService {
}
package com.spring;
import java.io.File;
import java.lang.annotation.Annotation;
import java.net.URL;
public class ApplicationContext {
private Class configClass;
public ApplicationContext(Class configClass) {
this.configClass = configClass;
/*1.根据传入的配置类拿到ComponentScan注解信息
2.获取扫描路径 包 com.tes.service--->需转为com/tes/service
3.根据获取到的扫描路径获取在路径包下所有类的信息
4.判断所扫描到的类上是否有Component注解,有的话表示当前类是一个Bean对象
......
* */
//解析配置类
//ComponentScan注解--->拿到扫描路径--->扫描
///在类上是否有注解
//1.
ComponentScan componentScanAnnotation
= (ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
//2.
String path = componentScanAnnotation.value();//获取注解 得到的值是否为扫描路径
System.out.println("扫描获取的路径(包): "+path); //com.tes.service 怎么根据包名得到报下面的所有类 类加载器
path=path.replace(".", "/");// --->转换为com/tes/service
System.out.println("转换后的路径(包): "+path);
//扫描
/*类加载器
* App--->classpath
* */
ClassLoader classLoader = ApplicationContext.class.getClassLoader();//
//通过类加载器获取某一资源
//3.
URL resource = classLoader.getResource(path);//相对路径
File file = new File(resource.getFile());
if (file.isDirectory()) {//是否为文件
File[] files = file.listFiles();
for (File f : files) {
System.out.println("获取结果绝对路径: "+"\n"+f);
String fileName = f.getAbsolutePath();
if (fileName.endsWith(".class")) {//是class文件才去下一步解析
String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
className = className.replace("\\", ".");//
System.out.println("提取后: "+className);
/*将得到的D:\project3\2109\spring_origin\target\classes\com\tes\service\UserService.class
* 转化为com.tes.service.UserService
* */
// Class> aClass = classLoader.loadClass("..");
try {
// Class> clazz = classLoader.loadClass("com.tes.service.UserService");
//根据名字加载类,得到calss对象
Class<?> clazz = classLoader.loadClass(className);
//4.扫描这个类上是否有Component注解
if (clazz.isAnnotationPresent(Component.class)) {
//判断所扫描到的类上是否有Component注解,有的话表示当前类是一个Bean
//...
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
public Object getBean(String beanName){
return null;
}
}
public static void main(String[] args) {
ApplicationContext applicationContext = new ApplicationContext(AppConfig.class);
System.out.println(applicationContext.getBean("userService"));
//System.out.println(applicationContext.getBean("userService"));
//System.out.println(applicationContext.getBean("userService"));
}
如何拿到beanName
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
String value();
}
bean的定义,当前类型,作用域
package com.spring;
public class BeanDefinition {
private Class clazz; //当前bean的类型
private String scope;
public Class getClazz() {
return clazz;
}
public void setClazz(Class clazz) {
this.clazz = clazz;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
}
package com.spring;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ApplicationContext {
private Class configClass;
private ConcurrentHashMap<String,Object> singletonObjects=new ConcurrentHashMap<>();//单例池
private ConcurrentHashMap<String,BeanDefinition> beanDefinitionMap=new ConcurrentHashMap<>();
public ApplicationContext(Class configClass) {
this.configClass = configClass;
/*1.根据传入的配置类拿到ComponentScan注解信息
2.获取扫描路径 包 com.tes.service--->需转为com/tes/service
3.根据获取到的扫描路径获取在路径包下所有类的信息
4.判断所扫描到的类上是否有Component注解,有的话表示当前类是一个Bean对象
......
* */
//解析配置类
//ComponentScan注解--->拿到扫描路径--->扫描--->BeanDefinition--->BeanDefinitionMap
///在类上是否有注解
//1.
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(beanDefinition);//
singletonObjects.put(beanName,bean);
}
}
}
public Object createBean(BeanDefinition beanDefinition){
Class clazz = beanDefinition.getClazz();
try {
Object instance = clazz.getDeclaredConstructor().newInstance();
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
private void scan(Class configClass) {
ComponentScan componentScanAnnotation
= (ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
//2.
String path = componentScanAnnotation.value();//获取注解 得到的值是否为扫描路径
System.out.println("扫描获取的路径(包): "+path); //com.tes.service 怎么根据包名得到报下面的所有类 类加载器
path=path.replace(".", "/");// --->转换为com/tes/service
System.out.println("转换后的路径(包): "+path);
//扫描
/*类加载器
* App--->classpath
* */
ClassLoader classLoader = ApplicationContext.class.getClassLoader();//
//通过类加载器获取某一资源
//3.
URL resource = classLoader.getResource(path);//相对路径
File file = new File(resource.getFile());
if (file.isDirectory()) {//是否为文件
File[] files = file.listFiles();
for (File f : files) {
System.out.println("获取结果绝对路径: "+"\n"+f);
String fileName = f.getAbsolutePath();
if (fileName.endsWith(".class")) {//是class文件才去下一步解析
String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
className = className.replace("\\", ".");//
System.out.println("提取后: "+className);
/*将得到的D:\project3\2109\spring_origin\target\classes\com\tes\service\UserService.class
* 转化为com.tes.service.UserService
* */
// Class> aClass = classLoader.loadClass("..");
try {
// Class> clazz = classLoader.loadClass("com.tes.service.UserService");
//根据名字加载类,得到calss对象
Class<?> clazz = classLoader.loadClass(className);
//4.扫描这个类上是否有Component注解
if (clazz.isAnnotationPresent(Component.class)) {
//判断所扫描到的类上是否有Component注解,有的话表示当前类是一个Bean
//...
//解析类-->BeanDefinition
Component componentAnnotation=clazz.getDeclaredAnnotation(Component.class);
String beanName = componentAnnotation.value();
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setClazz(clazz);
if (clazz.isAnnotationPresent(Scope.class)){
Scope scopeAnnotation=clazz.getDeclaredAnnotation(Scope.class);
beanDefinition.setScope(scopeAnnotation.value());
}else{
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
public Object getBean(String beanName){
if (beanDefinitionMap.containsKey(beanName)){
BeanDefinition beanDefinition=beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("singleton")){
Object o = singletonObjects.get(beanName);
return o;
}else {
//创建Bean
Object bean = createBean(beanDefinition);
return bean;
}
}else {
//不存在Bean
throw new NullPointerException();
}
// return null;
}
}