参考视频
https://www.bilibili.com/video/BV1tR4y1F75R?p=1
目录
手写spring
Test
package com.zs.service;
import com.zs.spring.ZsApplicationContext;
public class Test {
public static void main(String[] args) {
ZsApplicationContext zsApplicationContext = new ZsApplicationContext(AppConfig.class);
UserService userService = (UserService) zsApplicationContext.getBean("userService");
}
}
UserService
package com.zs.service;
import com.zs.spring.Component;
@Component("userService")
public class UserService {
}
ZsApplicationContext
package com.zs.spring;
public class ZsApplicationContext {
private Class configClass;
public ZsApplicationContext(Class configClass) {
this.configClass = configClass;
}
public Object getBean(String beanName) {
return null;
}
}
Component
package com.zs.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 "";
}
ComponentScan
package com.zs.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 "";
}
AppConfig
package com.zs.service;
import com.zs.spring.ComponentScan;
@ComponentScan("com.zs.service")
public class AppConfig {
}
模拟扫描
package com.zs.spring;
import com.sun.media.sound.SoftTuning;
import java.io.File;
import java.net.URL;
public class ZsApplicationContext {
private Class configClass;
public ZsApplicationContext(Class configClass) {
this.configClass = configClass;
if (configClass.isAnnotationPresent(ComponentScan.class)){
ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
String path = componentScanAnnotation.value();
path = path.replace(".","/");
ClassLoader classLoader = ZsApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
if (file.isDirectory()){
File[] files = file.listFiles();
for (File f : files) {
String fileName = f.getAbsolutePath();
if (fileName.endsWith(".class")){
try {
String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
className = className.replace("/",".");
System.out.println(className);
Class<?> clazz = classLoader.loadClass(className);
if (clazz.isAnnotationPresent(Component.class)){
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
}
public Object getBean(String beanName) {
return null;
}
}
模拟BeanDefinition
Scope
package com.zs.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 "";
}
BeanDefinition
package com.zs.spring;
public class BeanDefinition {
private Class type;
private String scope;
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;
}
}
ZsApplicationContext
package com.zs.spring;
import com.sun.media.sound.SoftTuning;
import java.io.File;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;
public class ZsApplicationContext {
private Class configClass;
private ConcurrentHashMap<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
public ZsApplicationContext(Class configClass) {
this.configClass = configClass;
if (configClass.isAnnotationPresent(ComponentScan.class)){
ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
String path = componentScanAnnotation.value();
path = path.replace(".","/");
ClassLoader classLoader = ZsApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
if (file.isDirectory()){
File[] files = file.listFiles();
for (File f : files) {
String fileName = f.getAbsolutePath();
if (fileName.endsWith(".class")){
try {
String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
className = className.replace("/",".");
System.out.println(className);
Class<?> clazz = classLoader.loadClass(className);
if (clazz.isAnnotationPresent(Component.class)){
Component component = clazz.getAnnotation(Component.class);
String beanName = component.value();
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(clazz);
if (clazz.isAnnotationPresent(Scope.class)){
Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
beanDefinition.setScope(scopeAnnotation.value());
}else{
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
}
public Object getBean(String beanName) {
return null;
}
}
模拟getBean
package com.zs.spring;
import com.sun.media.sound.SoftTuning;
import java.io.File;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;
public class ZsApplicationContext {
private Class configClass;
private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
public ZsApplicationContext(Class configClass) {
this.configClass = configClass;
if (configClass.isAnnotationPresent(ComponentScan.class)) {
ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
String path = componentScanAnnotation.value();
path = path.replace(".", "/");
ClassLoader classLoader = ZsApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
String fileName = f.getAbsolutePath();
if (fileName.endsWith(".class")) {
try {
String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
className = className.replace("/", ".");
System.out.println(className);
Class<?> clazz = classLoader.loadClass(className);
if (clazz.isAnnotationPresent(Component.class)) {
Component component = clazz.getAnnotation(Component.class);
String beanName = component.value();
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(clazz);
if (clazz.isAnnotationPresent(Scope.class)) {
Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
beanDefinition.setScope(scopeAnnotation.value());
} else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
for (String beanName : beanDefinitionMap.keySet()) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("singleton")){
Object bean = createBean(beanName,beanDefinition);
singletonObjects.put(beanName,bean);
}
}
}
private Object createBean(String beanName,BeanDefinition beanDefinition){
return null;
}
public Object getBean(String beanName) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition == null) {
throw new NullPointerException();
} else {
String scope = beanDefinition.getScope();
if (scope.equals("singleton")){
Object bean = singletonObjects.get(beanName);
if (bean == null){
Object o = createBean(beanName,beanDefinition);
singletonObjects.put(beanName,0);
}
return bean;
}else{
return createBean(beanName,beanDefinition);
}
}
}
}
createBean方法实现
private Object createBean(String beanName,BeanDefinition beanDefinition){
Class clazz = beanDefinition.getType();
try {
Object instance = clazz.getConstructor().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;
}
测试单例,多例
package com.zs.service;
import com.zs.spring.ZsApplicationContext;
public class Test {
public static void main(String[] args) {
ZsApplicationContext zsApplicationContext = new ZsApplicationContext(AppConfig.class);
System.out.println(zsApplicationContext.getBean("userService"));
System.out.println(zsApplicationContext.getBean("userService"));
System.out.println(zsApplicationContext.getBean("userService"));
}
}
模拟依赖注入
扫描时如果没有给名称默认给类名
if (beanName.equals("")){
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
OrderService
package com.zs.service;
import com.zs.spring.Component;
import com.zs.spring.Scope;
@Component
public class OrderService {
}
测试
package com.zs.service;
import com.zs.spring.ZsApplicationContext;
public class Test {
public static void main(String[] args) {
ZsApplicationContext zsApplicationContext = new ZsApplicationContext(AppConfig.class);
System.out.println(zsApplicationContext.getBean("userService"));
System.out.println(zsApplicationContext.getBean("userService"));
System.out.println(zsApplicationContext.getBean("userService"));
System.out.println(zsApplicationContext.getBean("orderService"));
}
}
package com.zs.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 {
}
UserService
package com.zs.service;
import com.zs.spring.Autowired;
import com.zs.spring.Component;
import com.zs.spring.Scope;
@Component("userService")
public class UserService {
@Autowired
private OrderService orderService;
public void test(){
System.out.println(orderService);
}
}
测试,获取为null
package com.zs.service;
import com.zs.spring.ZsApplicationContext;
public class Test {
public static void main(String[] args) {
ZsApplicationContext zsApplicationContext = new ZsApplicationContext(AppConfig.class);
UserService userService = (UserService) zsApplicationContext.getBean("userService");
userService.test();
}
}
依赖注入简单版实现
private Object createBean(String beanName,BeanDefinition beanDefinition){
Class clazz = beanDefinition.getType();
try {
Object instance = clazz.getConstructor().newInstance();
for (Field f : clazz.getDeclaredFields()) {
if (f.isAnnotationPresent(Autowired.class)){
f.setAccessible(true);
f.set(instance,getBean(f.getName()));
}
}
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
Aware回调
依赖注入以后判断是否 实现了 BeanNameAware接口,实现回调
private Object createBean(String beanName,BeanDefinition beanDefinition){
Class clazz = beanDefinition.getType();
try {
Object instance = clazz.getConstructor().newInstance();
for (Field f : clazz.getDeclaredFields()) {
if (f.isAnnotationPresent(Autowired.class)){
f.setAccessible(true);
f.set(instance,getBean(f.getName()));
}
}
if (instance instanceof BeanNameAware){
((BeanNameAware)instance).setBeanName(beanName);
}
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
package com.zs.spring;
public interface BeanNameAware {
void setBeanName(String beanName);
}
测试
package com.zs.service;
import com.zs.spring.Autowired;
import com.zs.spring.Component;
import com.zs.spring.Scope;
@Component("userService")
public class UserService {
@Autowired
private OrderService orderService;
public void test(){
System.out.println(orderService);
System.out.println(orderService.getBeanName());
}
}
package com.zs.service;
import com.zs.spring.BeanNameAware;
import com.zs.spring.Component;
import com.zs.spring.Scope;
@Component
public class OrderService implements BeanNameAware {
private String beanName;
public String getBeanName() {
return beanName;
}
@Override
public void setBeanName(String beanName) {
this.beanName = beanName;
}
}
初始化回调
private Object createBean(String beanName,BeanDefinition beanDefinition){
Class clazz = beanDefinition.getType();
try {
Object instance = clazz.getConstructor().newInstance();
for (Field f : clazz.getDeclaredFields()) {
if (f.isAnnotationPresent(Autowired.class)){
f.setAccessible(true);
f.set(instance,getBean(f.getName()));
}
}
if (instance instanceof BeanNameAware){
((BeanNameAware)instance).setBeanName(beanName);
}
if (instance instanceof InitializingBean){
((InitializingBean)instance).afterPropertiesSet();
}
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
模拟BeanPostProcessor
package com.zs.spring;
public interface BeanPostProcessor {
void postProcessBeforeInitialization(String beanName,Object bean);
void postProcessAfterInitialization(String beanName,Object bean);
}
private ArrayList<BeanPostProcessor> beanPostProcessorsList = new ArrayList<>();
构造方法中
if (clazz.isAnnotationPresent(Component.class)) {
if (BeanPostProcessor.class.isAssignableFrom(clazz)){
BeanPostProcessor instance = (BeanPostProcessor) clazz.newInstance();
beanPostProcessorsList.add(instance);
}
createBean方法中
for (BeanPostProcessor beanPostProcessor : beanPostProcessorsList) {
beanPostProcessor.postProcessBeforeInitialization(beanName,instance);
}
if (instance instanceof InitializingBean){
((InitializingBean)instance).afterPropertiesSet();
}
for (BeanPostProcessor beanPostProcessor : beanPostProcessorsList) {
beanPostProcessor.postProcessAfterInitialization(beanName,instance);
}
|