项目目的
在理解 Spring 系统结构、实现原理的基础上,自己动手写一个实现Spring核心功能的框架,以达到学习的目的。
项目入口
项目的入口为DispatcherSerlvet的init()方法中,在Servlet 的 init 方法初始化了IOC容器和Spring MVC所依赖的组件
项目搭建
本篇博客代码地址:https://github.com/jinzzzzz/spring-demo
用户配置
application.properties配置
application.properties作为配置文件,配置所需要的属性,配置如下:
1
| scanPackage=top.jinjinz.spring
|
web.xml 配置
配置自定义Servlet DispatcherServlet
及设置匹配请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:javaee="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <display-name>Web Application</display-name> <servlet> <servlet-name>mvc</servlet-name> <servlet-class>top.jinjinz.spring.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
|
项目配置
build.gradle配置
build.gradle配置相关的jar包依赖,目前只依赖了servlet api。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| subprojects { apply plugin: 'java'
group 'spring-demo'
repositories { mavenCentral() }
dependencies { compile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0' } }
|
项目模块
项目名 |
项目描述 |
spring-core |
IOC容器/依赖注入 |
spring-webmvc |
web框架,基于Servlet |
spring-aop |
AOP框架 |
spring-test |
测试项目 |
项目设计
spring-aop
实现切面功能,判断加上注解的类注册切面方法。
注解定义
定义aop相关注解@After
、@Aspect
、@Before
1 2 3 4 5 6 7 8
| @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface After {
String value();
String argNames() default ""; }
|
1 2 3 4 5
| @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Aspect { public String value() default ""; }
|
1 2 3 4 5 6 7 8 9
| @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Before {
String value();
String argNames() default "";
}
|
接口定义
Advice
1 2 3 4 5 6 7 8 9
| package top.jinjinz.spring.aop;
public interface Advice { }
|
AopProxy
1 2 3 4 5 6 7 8 9 10 11 12 13
| package top.jinjinz.spring.aop;
public interface AopProxy {
Object getProxy();
Object getProxy(ClassLoader classLoader); }
|
Joinpoint
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package top.jinjinz.spring.aop.intercept;
public interface Joinpoint {
Object proceed() throws Throwable;
Object getThis(); }
|
MethodInterceptor
1 2 3 4 5 6 7 8 9 10
| package top.jinjinz.spring.aop.intercept;
public interface MethodInterceptor { Object invoke(MethodInvocation invocation) throws Throwable; }
|
MethodInvocation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package top.jinjinz.spring.aop.intercept;
import java.lang.reflect.Method;
public interface MethodInvocation extends Joinpoint{
Method getMethod();
Object[] getArguments(); }
|
功能实现
AdvisedSupport
保存类方法执行时关联的调用链
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| package top.jinjinz.spring.aop;
import java.lang.reflect.Method; import java.util.List; import java.util.Map; import java.util.regex.Pattern;
public class AdvisedSupport {
private Class<?> targetClass;
private Object target;
private Pattern pointCutClassPattern;
private transient Map<Method, List<Object>> methodCache;
public List<Object> getInterceptorsAndDynamicInterceptionAdvice( Method method,Class<?> targetClass) throws Exception { List<Object> cached = this.methodCache.get(method); if (cached == null) { Method m = targetClass.getMethod(method.getName(),method.getParameterTypes()); cached = methodCache.get(m); this.methodCache.put(method, cached); } return cached; }
public Class<?> getTargetClass() { return targetClass; }
public void setTargetClass(Class<?> targetClass) { this.targetClass = targetClass; }
public Object getTarget() { return target; }
public void setTarget(Object target) { this.target = target; }
public Pattern getPointCutClassPattern() { return pointCutClassPattern; }
public void setPointCutClassPattern(Pattern pointCutClassPattern) { this.pointCutClassPattern = pointCutClassPattern; }
public Map<Method, List<Object>> getMethodCache() { return methodCache; }
public void setMethodCache(Map<Method, List<Object>> methodCache) { this.methodCache = methodCache; } }
|
JdkDynamicAopProxy
使用jdk动态代理,执行方法时,执行方法调用链
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| package top.jinjinz.spring.aop;
import top.jinjinz.spring.aop.intercept.MethodInvocation;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.List;
public class JdkDynamicAopProxy implements AopProxy, InvocationHandler {
private final AdvisedSupport advised;
public JdkDynamicAopProxy(AdvisedSupport config) throws Exception { this.advised = config; }
@Override public Object getProxy() { return getProxy(this.advised.getTargetClass().getClassLoader()); }
@Override public Object getProxy(ClassLoader classLoader) { return Proxy.newProxyInstance( classLoader,this.advised.getTargetClass().getInterfaces(),this); }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice( method,this.advised.getTargetClass()); if(null==chain){ return method.invoke(proxy, args); } MethodInvocation invocation = new ReflectiveMethodInvocation( proxy,advised.getTarget(),method,args,this.advised.getTargetClass(),chain); return invocation.proceed(); } }
|
ProxyFactory
生成代理对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package top.jinjinz.spring.aop;
import java.lang.reflect.Proxy;
public class ProxyFactory extends AdvisedSupport{
public Object getProxy() throws Exception { return createAopProxy().getProxy(); }
public Object getProxy(ClassLoader classLoader) throws Exception{ return createAopProxy().getProxy(classLoader); }
private synchronized AopProxy createAopProxy() throws Exception{ Class<?> targetClass = getTargetClass(); if (targetClass == null) { throw new Exception("没有代理目标类"); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(this); } return new JdkDynamicAopProxy(this); }
}
|
ReflectiveMethodInvocation
执行方法调用链
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| package top.jinjinz.spring.aop;
import top.jinjinz.spring.aop.intercept.MethodInterceptor; import top.jinjinz.spring.aop.intercept.MethodInvocation;
import java.lang.reflect.Method; import java.util.List; import java.util.Map;
public class ReflectiveMethodInvocation implements MethodInvocation {
protected final Object proxy;
protected final Object target;
protected final Method method;
protected Object[] arguments = new Object[0];
private final Class<?> targetClass;
private Map<String, Object> userAttributes;
protected final List<?> interceptorsAndDynamicMethodMatchers;
private int currentInterceptorIndex = -1;
public ReflectiveMethodInvocation( Object proxy,Object target, Method method,Object[] arguments, Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
this.proxy = proxy; this.target = target; this.targetClass = targetClass; this.method = method; this.arguments = arguments; this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers; }
@Override public Method getMethod() { return this.method; }
@Override public Object[] getArguments() { return this.arguments; }
@Override public Object proceed() throws Throwable { if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return this.method.invoke(this.target,this.arguments); } Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get( ++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof MethodInterceptor) { MethodInterceptor mi = (MethodInterceptor) interceptorOrInterceptionAdvice; return mi.invoke(this); } else { return proceed(); } }
@Override public Object getThis() { return this.target; } }
|
AutoProxyCreator
实现BeanPostProcessor接口,在初始化bean时调用,此时创建代理对象并加入调用方法链
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
| package top.jinjinz.spring.aop.autoproxy;
import top.jinjinz.spring.aop.AdvisedSupport; import top.jinjinz.spring.aop.ProxyFactory; import top.jinjinz.spring.aop.adapter.AfterReturningAdviceInterceptor; import top.jinjinz.spring.aop.adapter.MethodBeforeAdviceInterceptor; import top.jinjinz.spring.aop.annotation.After; import top.jinjinz.spring.aop.annotation.AfterThrowing; import top.jinjinz.spring.aop.annotation.AopProxyUtils; import top.jinjinz.spring.aop.annotation.Before; import top.jinjinz.spring.aop.aspectj.AspectJAdvice; import top.jinjinz.spring.beans.factory.BeanFactory; import top.jinjinz.spring.beans.factory.config.BeanPostProcessor;
import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern;
public class AutoProxyCreator implements BeanPostProcessor {
private final Map<String,List<AspectJAdvice>> aspectMethods;
private final List<String> patterns;
public AutoProxyCreator(Map<String, List<AspectJAdvice>> aspectMethods, List<String> patterns) { this.aspectMethods = aspectMethods; this.patterns = patterns; }
@Override public Object postProcessBeforeInitialization(Object bean, String beanName, BeanFactory beanFactory) throws Exception { if (bean != null) { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTarget(bean); proxyFactory.setTargetClass(bean.getClass()); proxyFactory.setMethodCache( getMethodCathe(proxyFactory,beanFactory,Before.class)); return proxyFactory.getProxy(); } return bean; }
@Override public Object postProcessAfterInitialization(Object bean, String beanName, BeanFactory beanFactory) throws Exception { if (bean != null) { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTarget(bean); proxyFactory.setTargetClass(bean.getClass()); proxyFactory.setMethodCache( getMethodCathe(proxyFactory,beanFactory,After.class)); return proxyFactory.getProxy(); } return bean; }
private List<Object> getAdvices( String p,BeanFactory beanFactory,Class<? extends Annotation> annotationClass) throws Exception{ List<Object> advices = new ArrayList<>(); List<AspectJAdvice> aspectJAdviceList = aspectMethods.get(p); for (AspectJAdvice aspectJAdvice:aspectJAdviceList) { if(aspectJAdvice.getAspectTarget() instanceof String){ aspectJAdvice.setAspectTarget( beanFactory.getBean((String)aspectJAdvice.getAspectTarget())); } if(aspectJAdvice.getAspectMethod().isAnnotationPresent(Before.class)){ advices.add(new MethodBeforeAdviceInterceptor(aspectJAdvice)); }else if(aspectJAdvice.getAspectMethod().isAnnotationPresent(After.class)){ advices.add(new AfterReturningAdviceInterceptor(aspectJAdvice)); } } return advices; }
private Map<Method, List<Object>> getMethodCathe( AdvisedSupport advisedSupport,BeanFactory beanFactory, Class<? extends Annotation> annotationClass) throws Exception{ Map<Method, List<Object>> methodCache = new HashMap<>(); Method[] methods=advisedSupport.getTargetClass().getMethods(); List<Object> advices; Matcher matcher; String methodString; Pattern pattern; for (Method method:methods) { methodString = method.toString(); if(methodString.contains("throws")){ methodString = methodString.substring(0,methodString.lastIndexOf("throws")).trim(); } for (String p:patterns){ pattern = Pattern.compile(p); matcher = pattern.matcher(methodString); if(matcher.matches()){ advices = getAdvices(p,beanFactory,annotationClass); methodCache.put(method,advices); break; } } } return methodCache; }
}
|
AspectJAdvice
保存配置需要切面执行的方法及方法的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package top.jinjinz.spring.aop.aspectj;
import java.lang.reflect.Method;
public class AspectJAdvice { private Method aspectMethod; private Object aspectTarget;
public AspectJAdvice(Method aspectMethod, Object aspectTarget) { this.aspectMethod = aspectMethod; this.aspectTarget = aspectTarget; }
public Method getAspectMethod() { return aspectMethod; }
public void setAspectMethod(Method aspectMethod) { this.aspectMethod = aspectMethod; }
public Object getAspectTarget() { return aspectTarget; }
public void setAspectTarget(Object aspectTarget) { this.aspectTarget = aspectTarget; } }
|
AbstractAspectJAdvice
Advice的抽象类,定义基本功能,执行配置的切面方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| package top.jinjinz.spring.aop.aspectj;
import top.jinjinz.spring.aop.Advice; import top.jinjinz.spring.aop.annotation.AopProxyUtils; import top.jinjinz.spring.aop.intercept.Joinpoint;
import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public abstract class AbstractAspectJAdvice implements Advice {
private AspectJAdvice aspectJAdvice;
public AbstractAspectJAdvice(AspectJAdvice aspectJAdvice) { this.aspectJAdvice = aspectJAdvice; }
protected Object invokeAdviceMethod(Joinpoint joinPoint, Object returnValue, Throwable tx) throws Throwable{ Class<?> [] paramTypes = this.aspectJAdvice.getAspectMethod().getParameterTypes(); if(paramTypes.length == 0){ return this.aspectJAdvice.getAspectMethod().invoke( aspectJAdvice.getAspectTarget()); }else{ Object [] args = new Object[paramTypes.length]; for (int i = 0; i < paramTypes.length; i ++) { if(paramTypes[i] == Throwable.class){ args[i] = tx; }else if(paramTypes[i] == Object.class){ args[i] = returnValue; }else if(paramTypes[i] == Joinpoint.class){ args[i] = joinPoint; } } return this.aspectJAdvice.getAspectMethod().invoke( AopProxyUtils.getTargetObject(aspectJAdvice.getAspectTarget()),args); } } }
|
MethodBeforeAdviceInterceptor
方法调用之前执行,继承了AbstractAspectJAdvice类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package top.jinjinz.spring.aop.adapter;
import top.jinjinz.spring.aop.aspectj.AbstractAspectJAdvice; import top.jinjinz.spring.aop.aspectj.AspectJAdvice; import top.jinjinz.spring.aop.intercept.Joinpoint; import top.jinjinz.spring.aop.intercept.MethodInterceptor; import top.jinjinz.spring.aop.intercept.MethodInvocation;
import java.lang.reflect.Method;
public class MethodBeforeAdviceInterceptor extends AbstractAspectJAdvice implements MethodInterceptor { private Joinpoint joinPoint; public MethodBeforeAdviceInterceptor(AspectJAdvice aspectJAdvice) { super(aspectJAdvice); }
private void before(Method method,Object[] args,Object target) throws Throwable{ super.invokeAdviceMethod(this.joinPoint,null,null); } @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { this.joinPoint = methodInvocation; before(methodInvocation.getMethod(), methodInvocation.getArguments(), methodInvocation.getThis()); return methodInvocation.proceed(); } }
|
AfterReturningAdviceInterceptor
方法调用之后执行,继承了AbstractAspectJAdvice类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package top.jinjinz.spring.aop.adapter;
import top.jinjinz.spring.aop.aspectj.AbstractAspectJAdvice; import top.jinjinz.spring.aop.aspectj.AspectJAdvice; import top.jinjinz.spring.aop.intercept.Joinpoint; import top.jinjinz.spring.aop.intercept.MethodInterceptor; import top.jinjinz.spring.aop.intercept.MethodInvocation;
import java.lang.reflect.Method;
public class AfterReturningAdviceInterceptor extends AbstractAspectJAdvice implements MethodInterceptor { private Joinpoint joinPoint; public AfterReturningAdviceInterceptor(AspectJAdvice aspectJAdvice) { super(aspectJAdvice); }
private void afterReturning(Object retVal,Method method, Object[] args, Object target) throws Throwable{ super.invokeAdviceMethod(this.joinPoint,null,null); } @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { Object retVal = methodInvocation.proceed(); this.joinPoint = methodInvocation; this.afterReturning(retVal,methodInvocation.getMethod(), methodInvocation.getArguments(),methodInvocation.getThis()); return retVal; } }
|
AopProxyUtils
获取aop代理前的原始类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package top.jinjinz.spring.aop.annotation;
import top.jinjinz.spring.aop.AdvisedSupport; import top.jinjinz.spring.aop.AopProxy;
import java.lang.reflect.Field; import java.lang.reflect.Proxy;
public class AopProxyUtils { public static Object getTargetObject(Object proxy) throws Exception{ if(!isAopProxy(proxy)){ return proxy; } return getProxyTargetObject(proxy); }
private static boolean isAopProxy(Object object){ return Proxy.isProxyClass(object.getClass()); }
private static Object getProxyTargetObject(Object proxy) throws Exception{ Field h = proxy.getClass().getSuperclass().getDeclaredField("h"); h.setAccessible(true); AopProxy aopProxy = (AopProxy) h.get(proxy); Field advised = aopProxy.getClass().getDeclaredField("advised"); advised.setAccessible(true); AdvisedSupport advisedSupport = (AdvisedSupport)advised.get(aopProxy); return getTargetObject(advisedSupport.getTarget()); }
}
|
spring-core
实现Spring的IOC容器及依赖注入功能
注解定义
注解模块,实现@Autowrited
、@Service
、@RequestParam
、@RequestMapping
、@Controller
等注解
@Autowired
1 2 3 4 5 6 7 8 9 10 11 12 13
| package top.jinjinz.spring.beans.factory.annotation; import java.lang.annotation.*;
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Autowired { String value() default ""; }
|
@Service
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package top.jinjinz.spring.beans.factory.annotation; import java.lang.annotation.*;
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Service { String value() default ""; }
|
@Component
1 2 3 4 5 6 7 8 9 10 11 12 13
| package top.jinjinz.spring.beans.factory.annotation; import java.lang.annotation.*;
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Component { String value() default ""; }
|
@RequestParam
1 2 3 4 5 6 7 8 9 10 11 12 13
| package top.jinjinz.spring.beans.factory.annotation; import java.lang.annotation.*;
@Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RequestParam { String value() default ""; }
|
@RequestMapping
1 2 3 4 5 6 7 8 9 10 11 12 13
| package top.jinjinz.spring.beans.factory.annotation; import java.lang.annotation.*;
@Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RequestMapping { String value() default ""; }
|
@Controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package top.jinjinz.spring.beans.factory.annotation; import java.lang.annotation.*;
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller { String value() default ""; }
|
接口定义
BeanFactory
创建Bean的工厂,也就是IOC容器,BeanFactory 作为基础的接口类,定义了 IOC 容器的基本功能。
1 2 3 4 5 6 7 8 9 10 11 12
| package top.jinjinz.spring.beans.factory;
public interface BeanFactory {
Object getBean(String name) throws Exception; }
|
ApplicationContext
定义ApplicationContext接口,继承BeanFactory的功能并扩展其功能,默认初始化所有bean。
1 2 3 4 5 6 7 8 9 10 11 12
| package top.jinjinz.spring.context;
import top.jinjinz.spring.beans.factory.BeanFactory;
public interface ApplicationContext extends BeanFactory { String[] getBeanDefinitionNames(); }
|
BeanDefinition
存储对Bean的解析信息类,BeanDefinition存储了解析后的Bean元信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package top.jinjinz.spring.beans.factory.config;
public interface BeanDefinition {
void setBeanClassName(String beanClassName);
String getBeanClassName();
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
void setFactoryBeanName(String factoryBeanName);
String getFactoryBeanName(); }
|
BeanPostProcessor
在初始化bean时回调接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package top.jinjinz.spring.beans.factory.config;
import top.jinjinz.spring.beans.factory.BeanFactory;
public interface BeanPostProcessor { default Object postProcessBeforeInitialization(Object bean, String beanName, BeanFactory beanFactory) throws Exception { return bean; }
default Object postProcessAfterInitialization(Object bean, String beanName, BeanFactory beanFactory) throws Exception { return bean; } }
|
BeanDefinitionReader
将配置信息解析为BeanDefinition的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package top.jinjinz.spring.beans.factory.support;
import java.io.IOException;
public interface BeanDefinitionReader {
BeanDefinitionRegistry getRegistry();
int loadBeanDefinitions(String location) throws IOException;
int loadBeanDefinitions(String... locations) throws IOException; }
|
BeanDefinitionRegistry
注册BeanDefinition并保存的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package top.jinjinz.spring.beans.factory.support;
import top.jinjinz.spring.beans.factory.config.BeanDefinition; import top.jinjinz.spring.beans.factory.config.BeanPostProcessor;
public interface BeanDefinitionRegistry {
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws Exception;
void removeBeanDefinition(String beanName);
BeanDefinition getBeanDefinition(String beanName);
boolean containsBeanDefinition(String beanName);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor); }
|
功能实现
DefaultListableBeanFactory
BeanFactory的默认实现类,也实现了BeanDefinitionRegistry接口,保存了BeanDefinition信息,实现了基本的依赖注入功能和IOC容器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
| package top.jinjinz.spring.beans.factory.support; import top.jinjinz.spring.beans.factory.BeanFactory; import top.jinjinz.spring.beans.factory.annotation.Autowired; import top.jinjinz.spring.beans.factory.config.BeanDefinition; import top.jinjinz.spring.beans.factory.config.BeanPostProcessor;
import java.lang.reflect.Field; import java.util.*; import java.util.concurrent.ConcurrentHashMap;
public class DefaultListableBeanFactory implements BeanFactory,BeanDefinitionRegistry { private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();
@Override public Object getBean(String name) throws Exception{ return doGetBean(name); }
@Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws Exception{ this.beanDefinitionMap.put(beanName, beanDefinition); }
@Override public void removeBeanDefinition(String beanName) { this.beanDefinitionMap.remove(beanName); }
@Override public BeanDefinition getBeanDefinition(String beanName){ BeanDefinition beanDefinition = this.beanDefinitionMap.get(beanName); return beanDefinition; }
@Override public boolean containsBeanDefinition(String beanName) { return this.beanDefinitionMap.containsKey(beanName); }
@Override public String[] getBeanDefinitionNames() { return this.beanDefinitionMap.keySet().toArray(new String[0]); }
@Override public int getBeanDefinitionCount() { return this.beanDefinitionMap.size(); }
@Override public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { this.beanPostProcessors.remove(beanPostProcessor); this.beanPostProcessors.add(beanPostProcessor); }
private Object doGetBean(final String beanName) throws Exception{ Object singletonInstance = this.singletonObjects.get(beanName); if(null != singletonInstance){ return singletonInstance; }
if(singletonsCurrentlyInCreation.contains(beanName)){ throw new RuntimeException(beanName+"发生循环引用"); }
Object instance = null; BeanDefinition beanDefinition = this.beanDefinitionMap.get(beanName); if(null == beanDefinition){ throw new RuntimeException(beanName+"不存在"); }
Class<?> clazz = Class.forName(beanDefinition.getBeanClassName()); instance = clazz.newInstance(); populateBean(instance,beanDefinition,clazz); instance = applyBeanPostProcessorsBeforeInitialization(instance, beanName);
this.singletonObjects.put(beanDefinition.getBeanClassName(),instance); this.singletonObjects.put(beanDefinition.getFactoryBeanName(),instance); return instance; }
private Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws Exception { Object result = existingBean; for (BeanPostProcessor beanProcessor : beanPostProcessors) { Object current = beanProcessor.postProcessBeforeInitialization(result, beanName,this); if (current == null) { return result; } result = current; } return result; }
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws Exception {
Object result = existingBean; for (BeanPostProcessor beanProcessor : beanPostProcessors) { Object current = beanProcessor.postProcessAfterInitialization(result, beanName,this); if (current == null) { return result; } result = current; } return result; }
private void populateBean(Object instance, BeanDefinition beanDefinition, Class<?> clazz) throws Exception{ Object autowiredBean; singletonsCurrentlyInCreation.add(beanDefinition.getBeanClassName()); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if(!field.isAnnotationPresent(Autowired.class)){ continue;}
Autowired autowired = field.getAnnotation(Autowired.class);
String autowiredBeanName = autowired.value().trim(); if("".equals(autowiredBeanName)){ autowiredBeanName = field.getType().getName(); }
field.setAccessible(true);
try { autowiredBean = this.singletonObjects.get(autowiredBeanName); if(null == autowiredBean){ getBean(autowiredBeanName); } field.set(instance,autowiredBean); } catch (IllegalAccessException e) { e.printStackTrace(); }
} singletonsCurrentlyInCreation.remove(beanDefinition.getBeanClassName()); } }
|
AbstractApplicationContext
定义ApplicationContext的抽象类,其中有启动容器方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package top.jinjinz.spring.context.support;
import top.jinjinz.spring.beans.factory.BeanFactory; import top.jinjinz.spring.context.ApplicationContext;
public abstract class AbstractApplicationContext implements ApplicationContext {
public void refresh() throws Exception{ BeanFactory beanFactory = obtainFreshBeanFactory(); }
protected BeanFactory obtainFreshBeanFactory() throws Exception{ refreshBeanFactory(); BeanFactory beanFactory = getBeanFactory(); return beanFactory; }
protected abstract void refreshBeanFactory() throws Exception;
public abstract BeanFactory getBeanFactory(); }
|
PropertiesApplicationContext
定义Properties配置文件的启动方式,扫描注解类并注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
| package top.jinjinz.spring.context.support;
import top.jinjinz.spring.beans.factory.BeanFactory; import top.jinjinz.spring.beans.factory.config.BeanDefinition; import top.jinjinz.spring.beans.factory.config.BeanPostProcessor; import top.jinjinz.spring.beans.factory.support.BeanDefinitionRegistry; import top.jinjinz.spring.beans.factory.support.DefaultListableBeanFactory; import top.jinjinz.spring.context.annotation.AnnotatedBeanDefinitionReader;
import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.*;
public class PropertiesApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private Properties config = new Properties();
private final String SCAN_PACKAGE = "scanPackage";
private Set<Class<?>> annotatedClasses = new LinkedHashSet<>();
private DefaultListableBeanFactory beanFactory;
public PropertiesApplicationContext(String... locations) throws Exception{ InputStream is = this.getClass().getClassLoader().getResourceAsStream( locations[0].replace("classpath:","")); try { config.load(is); } catch (IOException e) { e.printStackTrace(); }finally { if(null != is){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } doScanner(config.getProperty(SCAN_PACKAGE)); refresh(); }
@Override protected void refreshBeanFactory() throws Exception{ DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); this.beanFactory = beanFactory; loadBeanDefinitions(beanFactory); }
@Override public BeanFactory getBeanFactory() { return beanFactory; }
@Override public Object getBean(String beanName) throws Exception { return this.beanFactory.getBean(beanName); }
@Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws Exception{ this.beanFactory.registerBeanDefinition(beanName,beanDefinition); }
@Override public void removeBeanDefinition(String beanName) { this.beanFactory.removeBeanDefinition(beanName); }
@Override public BeanDefinition getBeanDefinition(String beanName) { return this.beanFactory.getBeanDefinition(beanName); }
@Override public boolean containsBeanDefinition(String beanName) { return this.beanFactory.containsBeanDefinition(beanName); }
@Override public String[] getBeanDefinitionNames() { return this.beanFactory.getBeanDefinitionNames(); }
@Override public int getBeanDefinitionCount() { return this.beanFactory.getBeanDefinitionCount(); }
@Override public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { this.beanFactory.addBeanPostProcessor(beanPostProcessor); }
private void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws Exception{ AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(beanFactory); if (!this.annotatedClasses.isEmpty()) { reader.register(this.annotatedClasses.toArray(new Class<?>[0])); }
String[] beanNames = beanFactory.getBeanDefinitionNames(); for (String beanName:beanNames) { getBean(beanName); } }
private void doScanner(String scanPackage) throws Exception { URL url = this.getClass().getClassLoader().getResource( "/" + scanPackage.replaceAll("\\.", "/")); if (null == url) { return; } File dir = new File(url.getFile()); File[] dirs = dir.listFiles(); if (null == dirs) { return; } for (File file : dirs) { if (file.isDirectory()) { doScanner(scanPackage + "." + file.getName()); } else { Class<?> beanClass = Class.forName( scanPackage + "." + file.getName().replace(".class", "").trim()); if (!beanClass.isInterface()) { this.annotatedClasses.add(beanClass); } } } } }
|
AbstractBeanDefinition
BeanDefinition的基本实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| package top.jinjinz.spring.beans.factory.support;
import top.jinjinz.spring.beans.factory.config.BeanDefinition;
public abstract class AbstractBeanDefinition implements BeanDefinition{
private volatile String beanClass;
private boolean lazyInit = false;
private String factoryBeanName;
protected AbstractBeanDefinition(){};
protected AbstractBeanDefinition(BeanDefinition original) { setBeanClassName(original.getBeanClassName()); setLazyInit(original.isLazyInit()); setFactoryBeanName(original.getFactoryBeanName()); }
@Override public void setBeanClassName(String beanClassName) { this.beanClass = beanClassName; }
@Override public String getBeanClassName() { return beanClass; }
@Override public void setLazyInit(boolean lazyInit) { this.lazyInit = lazyInit; }
@Override public boolean isLazyInit() { return this.lazyInit; }
@Override public void setFactoryBeanName(String factoryBeanName) { this.factoryBeanName = factoryBeanName; }
@Override public String getFactoryBeanName() { return this.factoryBeanName; } }
|
AbstractBeanDefinitionReader
BeanDefinitionReader基本实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| package top.jinjinz.spring.beans.factory.support;
import java.io.IOException;
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader{ private final BeanDefinitionRegistry registry;
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) { this.registry = registry; }
@Override public final BeanDefinitionRegistry getRegistry() { return this.registry; }
@Override public int loadBeanDefinitions(String... locations) throws IOException { int counter = 0; for (String location : locations) { counter += loadBeanDefinitions(location); } return counter; }
}
|
AnnotatedBeanDefinitionReader
扫描注解类,注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| package top.jinjinz.spring.context.annotation;
import top.jinjinz.spring.aop.annotation.After; import top.jinjinz.spring.aop.annotation.AfterThrowing; import top.jinjinz.spring.aop.annotation.Aspect; import top.jinjinz.spring.aop.annotation.Before; import top.jinjinz.spring.aop.aspectj.AspectJAdvice; import top.jinjinz.spring.aop.autoproxy.AutoProxyCreator; import top.jinjinz.spring.beans.factory.annotation.AnnotatedBeanDefinition; import top.jinjinz.spring.beans.factory.annotation.Component; import top.jinjinz.spring.beans.factory.annotation.Controller; import top.jinjinz.spring.beans.factory.annotation.Service; import top.jinjinz.spring.beans.factory.config.BeanDefinition; import top.jinjinz.spring.beans.factory.config.BeanPostProcessor; import top.jinjinz.spring.beans.factory.support.BeanDefinitionRegistry;
import java.lang.reflect.Method; import java.util.*;
public class AnnotatedBeanDefinitionReader {
private final BeanDefinitionRegistry registry;
private Map<String,List<AspectJAdvice>> aspectMethods = new HashMap<>();
private List<String> patterns = new ArrayList<>();
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) { this.registry = registry; }
public void register(Class<?>... annotatedClasses) throws Exception{ for (Class<?> annotatedClass : annotatedClasses) { registerBean(annotatedClass); } BeanPostProcessor autoProxyCreator = new AutoProxyCreator(aspectMethods,patterns); registry.addBeanPostProcessor(autoProxyCreator); }
public void registerBean(Class<?> annotatedClass) throws Exception{ if(isRegister(annotatedClass)){ doRegisterBean(annotatedClass); parseBean(annotatedClass); } }
private void parseBean(Class<?> annotatedClass) { if(annotatedClass.isAnnotationPresent(Aspect.class)){ parseAspect(annotatedClass); } }
private void parseAspect(Class<?> annotatedClass) { List<AspectJAdvice> aspectJAdviceList; Method[] methods=annotatedClass.getMethods(); String pointCut = ""; for (Method method:methods) { if(method.isAnnotationPresent(Before.class)){ pointCut = method.getAnnotation(Before.class).value(); } if(method.isAnnotationPresent(After.class)){ pointCut = method.getAnnotation(After.class).value(); } if(method.isAnnotationPresent(AfterThrowing.class)){ pointCut = method.getAnnotation(AfterThrowing.class).pointcut(); } if("".equals(pointCut)){ continue; } if(!patterns.contains(pointCut)){ patterns.add(pointCut); } aspectJAdviceList=aspectMethods.get(pointCut); if(null == aspectJAdviceList){ aspectJAdviceList = new ArrayList<>(); } aspectJAdviceList.add(new AspectJAdvice(method,annotatedClass.getName())); aspectMethods.put(pointCut,aspectJAdviceList); } }
private boolean isRegister(Class<?> annotatedClass){ return annotatedClass.isAnnotationPresent(Component.class)|| annotatedClass.isAnnotationPresent(Controller.class)|| annotatedClass.isAnnotationPresent(Service.class); }
private <T> void doRegisterBean(Class<T> annotatedClass) throws Exception{ registry.registerBeanDefinition(annotatedClass.getName(),doCreateBeanDefinition( toLowerFirstCase( annotatedClass.getSimpleName()),annotatedClass.getName())); Class<?> [] interfaces = annotatedClass.getInterfaces(); for (Class<?> i : interfaces) { registry.registerBeanDefinition( i.getName(),doCreateBeanDefinition(i.getName(),annotatedClass.getName())); } }
private BeanDefinition doCreateBeanDefinition(String factoryBeanName, String beanClassName){ BeanDefinition beanDefinition = new AnnotatedBeanDefinition();
beanDefinition.setBeanClassName(beanClassName); beanDefinition.setFactoryBeanName(factoryBeanName); return beanDefinition; }
private String toLowerFirstCase(String simpleName) { char [] chars = simpleName.toCharArray(); chars[0] += 32; return String.valueOf(chars); } }
|
spring-webmvc
基于servlet实现webmvc
接口定义
HandlerAdapter
执行方法并动态匹配参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package top.jinjinz.spring.web.servlet;
import top.jinjinz.spring.web.servlet.method.HandlerMethod;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
public interface HandlerAdapter { ModelAndView handle(HttpServletRequest request, HttpServletResponse response, HandlerMethod handler) throws Exception; }
|
HandlerMapping
Handler映射处理器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package top.jinjinz.spring.web.servlet;
import top.jinjinz.spring.web.servlet.method.HandlerMethod;
import javax.servlet.http.HttpServletRequest;
public interface HandlerMapping {
HandlerMethod getHandler(HttpServletRequest request) throws Exception; }
|
功能实现
DispatcherServlet
Servlet的启动类,作为启动入口实现核心逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
| package top.jinjinz.spring.web.servlet;
import top.jinjinz.spring.context.ApplicationContext; import top.jinjinz.spring.context.support.PropertiesApplicationContext; import top.jinjinz.spring.web.servlet.method.HandlerMethod; import top.jinjinz.spring.web.servlet.method.HandlerMethodAdapter; import top.jinjinz.spring.web.servlet.method.HandlerMethodMapping;
import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.*;
public class DispatcherServlet extends HttpServlet {
private HandlerMapping handlerMapping;
private HandlerAdapter handlerAdapter;
public DispatcherServlet(){ super(); }
public void init(ServletConfig config) throws ServletException { try { PropertiesApplicationContext context = new PropertiesApplicationContext("application.properties"); initStrategies(context); }catch (Exception e){ e.printStackTrace(); }
System.out.println("mvc is init"); }
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); }
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try{ doDispatch(req,resp); }catch(Exception e){ resp.getWriter().write("500 Exception,Details:\r\n" + Arrays.toString(e.getStackTrace()).replaceAll("\\[|\\]", "") .replaceAll(",\\s", "\r\n")); } }
private void doDispatch(HttpServletRequest req,HttpServletResponse resp) throws Exception{ HandlerMethod handler = handlerMapping.getHandler(req); if(null == handler){ resp.getWriter().write("404 Not Found"); return; } ModelAndView mv = handlerAdapter.handle(req,resp,handler); }
private void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }
private void initFlashMapManager(ApplicationContext context) { }
private void initViewResolvers(ApplicationContext context) { }
private void initRequestToViewNameTranslator(ApplicationContext context) { }
private void initHandlerExceptionResolvers(ApplicationContext context) { }
private void initHandlerAdapters(ApplicationContext context) { this.handlerAdapter = new HandlerMethodAdapter(); }
private void initHandlerMappings(ApplicationContext context) { this.handlerMapping = new HandlerMethodMapping(context); }
private void initThemeResolver(ApplicationContext context) { }
private void initLocaleResolver(ApplicationContext context) { }
private void initMultipartResolver(ApplicationContext context) { } }
|
HandlerMethod
封装Handler的信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package top.jinjinz.spring.web.servlet.method;
import java.lang.reflect.Method;
public class HandlerMethod {
private final Object bean;
private final Method method;
public HandlerMethod(Object bean, Method method) { this.bean = bean; this.method = method; }
public Object getBean() { return bean; }
public Method getMethod() { return method; } }
|
HandlerMethodAdapter
HandlerAdapter实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
| package top.jinjinz.spring.web.servlet.method;
import top.jinjinz.spring.beans.factory.annotation.RequestParam; import top.jinjinz.spring.web.servlet.HandlerAdapter; import top.jinjinz.spring.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.annotation.Annotation; import java.util.Arrays; import java.util.HashMap; import java.util.Map;
public class HandlerMethodAdapter implements HandlerAdapter {
@Override public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, HandlerMethod handler) throws Exception {
Map<String,Integer> paramIndexMapping = new HashMap<>();
Annotation[] [] pa = handler.getMethod().getParameterAnnotations(); for (int i = 0; i < pa.length ; i ++) { for(Annotation a : pa[i]){ if(a instanceof RequestParam){ String paramName = ((RequestParam) a).value(); if("".equals(paramName.trim())){ }else { paramIndexMapping.put(paramName, i); } } } }
Class<?> [] paramsTypes = handler.getMethod().getParameterTypes(); for (int i = 0; i < paramsTypes.length ; i ++) { Class<?> type = paramsTypes[i]; if(type == HttpServletRequest.class || type == HttpServletResponse.class){ paramIndexMapping.put(type.getName(),i); } }
Map<String,String[]> params = request.getParameterMap();
Object [] paramValues = new Object[paramsTypes.length];
for (Map.Entry<String, String[]> parm : params.entrySet()) { String value = Arrays.toString(parm.getValue()) .replaceAll("\\[|\\]","").replaceAll("\\s",",");
if(!paramIndexMapping.containsKey(parm.getKey())){continue;}
int index = paramIndexMapping.get(parm.getKey()); paramValues[index] = caseStringValue(value,paramsTypes[index]); }
if(paramIndexMapping.containsKey(HttpServletRequest.class.getName())) { int reqIndex = paramIndexMapping.get(HttpServletRequest.class.getName()); paramValues[reqIndex] = request; }
if(paramIndexMapping.containsKey(HttpServletResponse.class.getName())) { int respIndex = paramIndexMapping.get(HttpServletResponse.class.getName()); paramValues[respIndex] = response; }
Object result = handler.getMethod().invoke(handler.getBean(),paramValues); if(result == null || result instanceof Void){ return null; }
boolean isModelAndView = handler.getMethod().getReturnType() == ModelAndView.class; if(isModelAndView){ return (ModelAndView) result; } return null; }
private Object caseStringValue(String value, Class<?> paramsType) { if(String.class == paramsType){ return value; } if(Integer.class == paramsType){ return Integer.valueOf(value); } else if(Double.class == paramsType){ return Double.valueOf(value); }
return value; } }
|
HandlerMethodMapping
HandlerMapping的实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
| package top.jinjinz.spring.web.servlet.method;
import top.jinjinz.spring.aop.annotation.AopProxyUtils; import top.jinjinz.spring.beans.factory.annotation.Controller; import top.jinjinz.spring.beans.factory.annotation.RequestMapping; import top.jinjinz.spring.context.ApplicationContext; import top.jinjinz.spring.web.servlet.HandlerMapping;
import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.util.*;
public class HandlerMethodMapping implements HandlerMapping {
private final MappingRegistry mappingRegistry = new MappingRegistry();
public HandlerMethodMapping(ApplicationContext context) { initHandlerMethod(context); }
@Override public final HandlerMethod getHandler(HttpServletRequest request) throws Exception { String url = request.getRequestURI(); String contextPath = request.getContextPath(); url = url.replace(contextPath, "").replaceAll("/+", "/"); return this.mappingRegistry.getHandlerMethod(url); }
private void initHandlerMethod(ApplicationContext context) { String [] beanNames = context.getBeanDefinitionNames(); try { for (String beanName : beanNames) {
Object bean = context.getBean(beanName); Object target = AopProxyUtils.getTargetObject(bean);
Class<?> clazz = target.getClass();
if(!clazz.isAnnotationPresent(Controller.class)){ continue; }
String baseUrl = ""; if(clazz.isAnnotationPresent(RequestMapping.class)){ RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class); baseUrl = requestMapping.value(); }
Method[] methods = clazz.getMethods(); for (Method method : methods) {
if(!method.isAnnotationPresent(RequestMapping.class)){ continue; }
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
String regex = ("/" + baseUrl + "/" + requestMapping.value(). replaceAll("\\*",".*")).replaceAll("/+", "/");
this.mappingRegistry.register(regex,target,method); System.out.println("Mapped " + regex + "," + method); } } }catch (Exception e){ e.printStackTrace(); } }
private HandlerMethod createHandlerMethod(Object handler, Method method) { return new HandlerMethod(handler, method); }
class MappingRegistry {
private final Map<String, MappingRegistration<String>> registry = new HashMap<>();
private final Map<String, HandlerMethod> mappingLookup = new LinkedHashMap<>();
public Map<String, HandlerMethod> getMappings() { return this.mappingLookup; }
public HandlerMethod getHandlerMethod(String mappings) { return this.mappingLookup.get(mappings); }
public void register(String mapping, Object handler, Method method) { HandlerMethod handlerMethod = createHandlerMethod(handler, method); this.mappingLookup.put(mapping, handlerMethod); } }
private static class MappingRegistration<T> {
private final T mapping;
private final HandlerMethod handlerMethod;
public MappingRegistration(T mapping, HandlerMethod handlerMethod) { this.mapping = mapping; this.handlerMethod = handlerMethod; }
public T getMapping() { return this.mapping; }
public HandlerMethod getHandlerMethod() { return this.handlerMethod; } }
}
|
功能测试
spring-test
service
配置Service
1 2 3 4 5 6 7 8 9 10
| package top.jinjinz.spring.test.service;
public interface DemoService { String hello(String name); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package top.jinjinz.spring.test.service.impl;
import top.jinjinz.spring.beans.factory.annotation.Service; import top.jinjinz.spring.test.service.DemoService;
@Service public class DemoServiceImpl implements DemoService {
@Override public String hello(String name) { String hello = "hello "+name; System.out.println("执行方法返回:"+hello); return hello; } }
|
controller
配置Controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| package top.jinjinz.spring.test.controller;
import top.jinjinz.spring.beans.factory.annotation.Autowired; import top.jinjinz.spring.beans.factory.annotation.Controller; import top.jinjinz.spring.beans.factory.annotation.RequestMapping; import top.jinjinz.spring.beans.factory.annotation.RequestParam; import top.jinjinz.spring.test.service.DemoService;
import javax.servlet.http.HttpServletResponse;
@Controller @RequestMapping("/demo") public class DemoController {
@Autowired private DemoService demoService;
@RequestMapping("/hello") public void hello(@RequestParam("name") String name, HttpServletResponse resp) throws Exception{ resp.getWriter().write(demoService.hello(name)); } }
|
aspect
配置切面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package top.jinjinz.spring.test.aspect;
import top.jinjinz.spring.aop.annotation.After; import top.jinjinz.spring.aop.annotation.Aspect; import top.jinjinz.spring.aop.annotation.Before; import top.jinjinz.spring.aop.intercept.Joinpoint; import top.jinjinz.spring.beans.factory.annotation.Component;
import java.util.Arrays;
@Aspect @Component public class LogAspect {
@Before("public .* top.jinjinz.spring.test.service..*Service..*(.*)") public void before(Joinpoint joinPoint){ System.out.println("执行方法前"); }
@After("public .* top.jinjinz.spring.test.service..*Service..*(.*)") public void after(Joinpoint joinPoint){ System.out.println("执行方法后"); }
}
|
application.properties
application.properties作为配置文件,配置所需要的属性
1
| scanPackage=top.jinjinz.spring
|
web.xml
配置自定义Servlet DispatcherServlet
及设置匹配请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:javaee="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <display-name>Web Application</display-name> <servlet> <servlet-name>mvc</servlet-name> <servlet-class>top.jinjinz.spring.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
|
测试效果