目录
我看过spring 源码,spring 核心在于 refresh()的13个方法,很多人,包括我,也很好奇是怎么实现的,今天,手写一个简单的spring ,帮助理解。文中所有的代码全是手写的,只依赖一个cglib包。
项目结构:
1、自定义一个spring的容器
pom.xml文件:
<dependencies>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
刚学pring的时候,都是这样用spring:
ApplicationContext ac = new ClassPathXmlApplicationContext("aop.xml");
MyCalculator bean = ac.getBean(MyCalculator.class);
System.out.println(bean.toString());
我们自己实现一个spring容器
package com.hdg.spring.springframework;
import com.hdg.spring.springframework.annotation.*;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class HDGApplicationContext {
private Class configClass;
private Map<String,HDGBeanDefinition> beanDefinitionMap=new HashMap<>();
private Map<String,Object> sinigletonObject=new HashMap<>();
public HDGApplicationContext(Class configClass) {
//扫描
scanBean(configClass);
this.configClass = configClass;
//创建非懒加载的bean
for(String beanName : beanDefinitionMap.keySet()){
HDGBeanDefinition hdgBeanDefinition = beanDefinitionMap.get(beanName);
if(hdgBeanDefinition.getScope().equals("singleton") && !hdgBeanDefinition.isLazy()){
Object bean = createBean(beanName, hdgBeanDefinition);
sinigletonObject.put(beanName,bean);
}
}
}
public Object createBean(String beanName,HDGBeanDefinition hdgBeanDefinition){
Class clazz = hdgBeanDefinition.getClazz();
Object instance = null;
try {
instance = clazz.newInstance();
for(Field field: instance.getClass().getDeclaredFields()) {
if(field.isAnnotationPresent(HDGAutowired.class)){
field.setAccessible(true);
// field.set(instance,getBean(field.getName()));
field.set(instance,getBean(field.getType()));
}
}
if(instance instanceof HDGApplicationContextAware){
((HDGApplicationContextAware)instance).setApplicationContext(this);
}
if(instance instanceof HDGBeanNameAware){
((HDGBeanNameAware)instance).setBeanName(beanName);
}
Object target=instance;
if(clazz.isAnnotationPresent(HDGTransactional.class)){
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("开户事务");
Object result = method.invoke(target, objects);
System.out.println("提交事务");
return result;
}
});
instance = enhancer.create();
}
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return instance;
}
private void scanBean(Class configClass) {
if(configClass.isAnnotationPresent(HDGComponentScan.class)){
HDGComponentScan annotation = (HDGComponentScan) configClass.getAnnotation(HDGComponentScan.class);
String path = annotation.value();
System.out.println("path="+path);//path=com.hdg.spring.user
path=path.replace(".","/");
//类加载器:AppClassLoader
ClassLoader classLoader = this.getClass().getClassLoader();
URL resource = classLoader.getResource(path);
File file=new File(resource.getFile());
List<File> classList=new ArrayList<>();
if(file.isDirectory()){
// System.out.println("file="+file);
for(File listFile:file.listFiles()){
// System.out.println(listFile);
if(listFile.isDirectory()){
for(File f:listFile.listFiles()){
if(!f.isDirectory()){
classList.add(f);
}
}
}else{
classList.add(listFile);
}
}
}
for (File file1 :classList) {
// System.out.println("file1="+file1);
String absolutePath = file1.getAbsolutePath();
String className=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"))
.replace("\\",".");
// System.out.println("className="+className);
try {
// Class<?> aClass = classLoader.loadClass("com.hdg.spring.user.service.OrderService");
Class<?> aClass = classLoader.loadClass(className);
if(aClass.isAnnotationPresent(HDGComponent.class)){
// System.out.println("className2="+className);
//判断是否多例,懒加载
HDGBeanDefinition hdgBeanDefinition=new HDGBeanDefinition();
hdgBeanDefinition.setClazz(aClass);
if(aClass.isAnnotationPresent(HDGScope.class)){
hdgBeanDefinition.setScope(aClass.getAnnotation(HDGScope.class).value());
}else{
hdgBeanDefinition.setScope("singleton");
}
String beanName = aClass.getAnnotation(HDGComponent.class).value();
if(beanName.isEmpty()){
//jdk自带的首字母小写的工具类
beanName= Introspector.decapitalize(aClass.getSimpleName());
}
System.out.println("beanName="+beanName);
beanDefinitionMap.put(beanName,hdgBeanDefinition);
hdgBeanDefinition.setLazy(aClass.isAnnotationPresent(HDGLazy.class));
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
}
//根据类型
private Object getBean(Class beanClass){
for (String beanName:beanDefinitionMap.keySet()){
HDGBeanDefinition hdgBeanDefinition=beanDefinitionMap.get(beanName);
if(hdgBeanDefinition.getClazz().equals(beanClass)){
return getBean(beanName);
}
}
return null;
}
public Object getBean(String beanName){
if(!beanDefinitionMap.containsKey(beanName)){
throw new NullPointerException();
}
HDGBeanDefinition hdgBeanDefinition = beanDefinitionMap.get(beanName);
if (hdgBeanDefinition.getScope().equals("singleton")) {
Object bean = sinigletonObject.get(beanName);
if(bean ==null){
bean = createBean(beanName, hdgBeanDefinition);
sinigletonObject.put(beanName,bean);
}
return bean;
}else{
return createBean(beanName,hdgBeanDefinition);
}
}
}
我们自己定义一个BeanDefinition
package com.hdg.spring.springframework;
public class HDGBeanDefinition {
private Class clazz;
private String scope;
private boolean isLazy;
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;
}
public boolean isLazy() {
return isLazy;
}
public void setLazy(boolean lazy) {
isLazy = lazy;
}
}
2 、自定义注解
实现平时用的注解
package com.hdg.spring.springframework.annotation;
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, ElementType.METHOD})
public @interface HDGAutowired {
boolean required() default true;
}
package com.hdg.spring.springframework.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface HDGComponent {
String value() default "";
}
package com.hdg.spring.springframework.annotation;
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 HDGComponentScan {
String value() default "";
}
package com.hdg.spring.springframework.annotation;
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, ElementType.METHOD})
public @interface HDGLazy {
}
package com.hdg.spring.springframework.annotation;
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 HDGScope {
// String value() default "singleton";
String value() default "";
}
package com.hdg.spring.springframework.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface HDGTransactional {
}
3、自定义aware 接口
我们自定义aware接口,spring的实现原理,跟我这里差不多
package com.hdg.spring.springframework.aware;
import com.hdg.spring.springframework.HDGApplicationContext;
public interface HDGApplicationContextAware {
void setApplicationContext(HDGApplicationContext applicationContext);
}
package com.hdg.spring.springframework.aware;
public interface HDGBeanNameAware {
void setBeanName(String beanName);
}
4、自定义Servcie
package com.hdg.spring.user.service;
import com.hdg.spring.springframework.annotation.HDGAutowired;
import com.hdg.spring.springframework.annotation.HDGComponent;
import com.hdg.spring.springframework.annotation.HDGTransactional;
@HDGComponent
@HDGTransactional
public class AOPService {
@HDGAutowired
private BService userService;
public void test(){
System.out.println("userService="+userService);
}
}
package com.hdg.spring.user.service;
import com.hdg.spring.springframework.annotation.HDGComponent;
@HDGComponent
public class AService {
}
package com.hdg.spring.user.service;
import com.hdg.spring.springframework.*;
import com.hdg.spring.springframework.annotation.HDGAutowired;
import com.hdg.spring.springframework.annotation.HDGComponent;
import com.hdg.spring.springframework.annotation.HDGLazy;
import com.hdg.spring.springframework.aware.HDGApplicationContextAware;
import com.hdg.spring.springframework.aware.HDGBeanNameAware;
@HDGComponent
//@HDGScope("prototype")
@HDGLazy
public class BService implements HDGApplicationContextAware, HDGBeanNameAware {
@HDGAutowired
private AService xxxx;
private HDGApplicationContext hdgApplicationContext;
private String beanName;
public void test(){
System.out.println("orderService="+xxxx);
System.out.println("hdgApplicationContext="+hdgApplicationContext);
System.out.println("beanName="+beanName);
}
@Override
public void setApplicationContext(HDGApplicationContext applicationContext) {
this.hdgApplicationContext=applicationContext;
}
@Override
public void setBeanName(String beanName) {
this.beanName=beanName;
}
}
5、自定义配置,运行类
package com.hdg.spring.user;
import com.hdg.spring.springframework.annotation.HDGComponentScan;
@HDGComponentScan("com.hdg.spring.user")
public class APPconfig {
}
package com.hdg.spring.user;
import com.hdg.spring.springframework.HDGApplicationContext;
import com.hdg.spring.user.service.AOPService;
public class MyApplication {
public static void main(String[] args) {
HDGApplicationContext applicationContext=new HDGApplicationContext(APPconfig.class);
AOPService aopService = (AOPService)applicationContext.getBean("AOPService");
aopService.test();
}
}
代码就写完了,可以实现spring的简单功能了,spring底层其实也是这样实现的
这里还实现了AOP