类图(手写版类图是原版迷你版) 手写版Spring启动流程图
手写版调用流程图 项目结构图
代码:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.giant-gator.spring</groupId>
<artifactId>gator-spring</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gator.spring</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
<build>
<finalName>${artifactId}</finalName>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<includes>
<include>***.java</exclude>
<exclude>***.*</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.26</version>
<configuration>
<webDefaultXml>src/main/resources/webdefault.xml</webDefaultXml>
<contextPath>/</contextPath>
<connectors>
<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
<port>80</port>
</connector>
</connectors>
<scanIntervalSeconds>0</scanIntervalSeconds>
<scanTargetPatterns>
<scanTargetPattern>
<directory>src/main/webapp</directory>
<includes>
<include>***.properties</include>
</includes>
</scanTargetPattern>
</scanTargetPatterns>
<systemProperties>
<systemProperty>
<name>
javax.xml.parsers.DocumentBuilderFactory
</name>
<value>
com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
</value>
</systemProperty>
<systemProperty>
<name>
javax.xml.parsers.SAXParserFactory
</name>
<value>
com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
</value>
</systemProperty>
<systemProperty>
<name>
javax.xml.transform.TransformerFactory
</name>
<value>
com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
</value>
</systemProperty>
<systemProperty>
<name>org.eclipse.jetty.util.URI.charset</name>
<value>UTF-8</value>
</systemProperty>
</systemProperties>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
<webResources>
<resource>
<!-- this is relative to the pom.xml directory -->
<directory>src/main/resources/</directory>
<targetPath>WEB-INF/classes</targetPath>
<includes>
<include>**
切面类
package com.gator.spring.executor.aspect;
import com.gator.spring.framework.aop.aspect.PABLO_JoinPoint;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
@Slf4j
public class LogAspect {
public void before(PABLO_JoinPoint joinPoint){
joinPoint.setUserAttribute("startTime_" + joinPoint.getMethod().getName(),System.currentTimeMillis());
log.info("Invoker Before Method!!!" +
"\nTargetObject:" + joinPoint.getThis() +
"\nArgs:" + Arrays.toString(joinPoint.getArguments()));
}
public void after(PABLO_JoinPoint joinPoint){
log.info("Invoker After Method!!!" +
"\nTargetObject:" + joinPoint.getThis() +
"\nArgs:" + Arrays.toString(joinPoint.getArguments()));
long startTime = (Long) joinPoint.getUserAttribute("startTime_" + joinPoint.getMethod().getName());
long endTime = System.currentTimeMillis();
System.out.println("use time :" + (endTime - startTime));
}
public void afterThrowing(PABLO_JoinPoint joinPoint, Throwable ex){
log.info("出现异常" +
"\nTargetObject:" + joinPoint.getThis() +
"\nArgs:" + Arrays.toString(joinPoint.getArguments()) +
"\nThrows:" + ex.getMessage());
}
}
controller
package com.gator.spring.executor.controller;
import com.gator.spring.executor.service.IModifyService;
import com.gator.spring.executor.service.IQueryService;
import com.gator.spring.framework.annotation.PABLO_Autowired;
import com.gator.spring.framework.annotation.PABLO_Controller;
import com.gator.spring.framework.annotation.PABLO_RequestMapping;
import com.gator.spring.framework.annotation.PABLO_RequestParam;
import com.gator.spring.framework.webmvc.servlet.PABLO_ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
@PABLO_Controller
@PABLO_RequestMapping("/web")
public class MyTestController {
@PABLO_Autowired
IQueryService queryService;
@PABLO_Autowired
IModifyService modifyService;
@PABLO_RequestMapping("/query.json")
public PABLO_ModelAndView query(HttpServletRequest request, HttpServletResponse response,
@PABLO_RequestParam("name") String name) {
String result = queryService.query(name);
return out(response, result);
}
@PABLO_RequestMapping("/add*.json")
public PABLO_ModelAndView add(HttpServletRequest request, HttpServletResponse response,
@PABLO_RequestParam("name") String name, @PABLO_RequestParam("addr") String addr) {
String result = modifyService.add(name, addr);
return out(response, result);
}
@PABLO_RequestMapping("/remove.json")
public PABLO_ModelAndView remove(HttpServletRequest request, HttpServletResponse response,
@PABLO_RequestParam("id") Integer id) {
String result = modifyService.remove(id);
return out(response, result);
}
@PABLO_RequestMapping("/edit.json")
public PABLO_ModelAndView edit(HttpServletRequest request, HttpServletResponse response,
@PABLO_RequestParam("id") Integer id,
@PABLO_RequestParam("name") String name) {
String result = modifyService.edit(id, name);
return out(response, result);
}
private PABLO_ModelAndView out(HttpServletResponse resp, String str) {
try {
Map<String,String> model = new HashMap<>();
model.put("teacher","pablo");
model.put("token","djhsjksmcvnff65f46ds5654xcss");
model.put("data","何章怀晓");
PABLO_ModelAndView pablo_modelAndView = new PABLO_ModelAndView("first",model);
return pablo_modelAndView;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
接口
package com.gator.spring.executor.service;
public interface IModifyService {
public String add(String name, String addr);
public String edit(Integer id, String name);
public String remove(Integer id);
}
public interface IQueryService {
public String query(String name);
}
实现类
@PABLO_Service
public class ModifyServiceImpl implements IModifyService {
public String add(String name,String addr) {
return "modifyService add,name=" + name + ",addr=" + addr;
}
public String edit(Integer id,String name) {
return "modifyService edit,id=" + id + ",name=" + name;
}
public String remove(Integer id) {
return "modifyService id=" + id;
}
@Override
public String toString() {
return "ModifyServiceImpl{}";
}
}
@PABLO_Service
@Slf4j
public class QueryServiceImpl implements IQueryService {
public String query(String name) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(new Date());
String json = "{name:\"" + name + "\",time:\"" + time + "\"}";
log.info("这是在业务方法中打印的:" + json);
return json;
}
@Override
public String toString() {
return "QueryServiceImpl{}";
}
}
注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PABLO_Autowired {
String value() default "";
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PABLO_Controller {
String value() default "";
}
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PABLO_RequestMapping {
String value() default "";
}
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PABLO_RequestParam {
String value() default "";
boolean required() default true;
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PABLO_Service {
String value() default "";
}
aspect
package com.gator.spring.framework.aop.aspect;
import java.lang.reflect.Method;
public abstract class PABLO_AbstractAspectAdvice {
private Method aspectMethod;
private Object aspectTarget;
public PABLO_AbstractAspectAdvice(Method aspectMethod, Object aspectTarget) {
this.aspectMethod = aspectMethod;
this.aspectTarget = aspectTarget;
}
public Object invokeAdviceMethod(PABLO_JoinPoint joinPoint, Object returnValue, Throwable tx) throws Throwable {
Class<?>[] paramTypes = this.aspectMethod.getParameterTypes();
if (null == paramTypes || paramTypes.length == 0) {
return this.aspectMethod.invoke(aspectTarget);
} else {
Object[] args = new Object[paramTypes.length];
for (int i = 0; i < paramTypes.length; i++) {
if (paramTypes[i] == PABLO_JoinPoint.class) {
args[i] = joinPoint;
} else if (paramTypes[i] == Throwable.class) {
args[i] = tx;
} else if (paramTypes[i] == Object.class) {
args[i] = returnValue;
}
}
return this.aspectMethod.invoke(aspectTarget, args);
}
}
}
public class PABLO_AfterReturningAdviceInterceptor
extends PABLO_AbstractAspectAdvice
implements PABLO_Advice, PABLO_MethodInterceptor {
private PABLO_JoinPoint joinPoint;
public PABLO_AfterReturningAdviceInterceptor(Method aspectMethod, Object aspectTarget) {
super(aspectMethod, aspectTarget);
}
@Override
public Object invoke(PABLO_MethodInvocation invocation) throws Throwable {
Object retVal = invocation.proceed();
this.joinPoint = invocation;
this.afterReturning(retVal,invocation.getMethod(),invocation.getArguments(),invocation.getThis());
return retVal;
}
private void afterReturning(Object retVal, Method method, Object[] arguments, Object aThis) throws Throwable {
super.invokeAdviceMethod(this.joinPoint,retVal,null);
}
}
public class PABLO_AfterThrowingAdviceInterceptor
extends PABLO_AbstractAspectAdvice
implements PABLO_Advice, PABLO_MethodInterceptor {
private String throwingName;
public PABLO_AfterThrowingAdviceInterceptor(Method aspectMethod, Object aspectTarget) {
super(aspectMethod, aspectTarget);
}
@Override
public Object invoke(PABLO_MethodInvocation invocation) throws Throwable {
try {
return invocation.proceed();
}catch (Throwable e){
invokeAdviceMethod(invocation,null,e.getCause());
throw e;
}
}
public void setThrowName(String throwName){
this.throwingName = throwName;
}
}
public interface PABLO_JoinPoint {
Object getThis();
Object[] getArguments();
Method getMethod();
void setUserAttribute(String key, Object value);
Object getUserAttribute(String key);
}
public class PABLO_MethodBeforeAdviceInterceptor
extends PABLO_AbstractAspectAdvice
implements PABLO_Advice, PABLO_MethodInterceptor {
private PABLO_JoinPoint joinPoint;
public PABLO_MethodBeforeAdviceInterceptor(Method aspectMethod, Object aspectTarget) {
super(aspectMethod, aspectTarget);
}
private void before(Method method,Object[] args,Object target) throws Throwable{
super.invokeAdviceMethod(this.joinPoint,null,null);
}
@Override
public Object invoke(PABLO_MethodInvocation invocation) throws Throwable {
this.joinPoint = invocation;
before(invocation.getMethod(), invocation.getArguments(), invocation.getThis());
return invocation.proceed();
}
}
aopconfig
@Data
public class PABLO_AopConfig {
private String pointCut;
private String aspectBefore;
private String aspectAfter;
private String aspectClass;
private String aspectAfterThrow;
private String aspectAfterThrowingName;
}
intercepter
public interface PABLO_MethodInterceptor {
Object invoke(PABLO_MethodInvocation invocation) throws Throwable;
}
package com.gator.spring.framework.aop.intercept;
import com.gator.spring.framework.aop.aspect.PABLO_JoinPoint;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class PABLO_MethodInvocation implements PABLO_JoinPoint {
private Object proxy;
private Method method;
private Object target;
private Object[] arguments;
private List<Object> interceptorsAndDynamicMethodMatchers;
private Class<?> targetClass;
private Map<String, Object> userAttributes;
private int currentInterceptorIndex = -1;
public PABLO_MethodInvocation(
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;
}
public Object proceed() throws Throwable {
if (Objects.isNull(this.interceptorsAndDynamicMethodMatchers)
|| this.interceptorsAndDynamicMethodMatchers.isEmpty()
|| this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return this.method.invoke(this.target, this.arguments);
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof PABLO_MethodInterceptor) {
PABLO_MethodInterceptor mi = (PABLO_MethodInterceptor) interceptorOrInterceptionAdvice;
return mi.invoke(this);
} else {
return proceed();
}
}
@Override
public Object getThis() {
return this.target;
}
@Override
public Object[] getArguments() {
return this.arguments;
}
@Override
public Method getMethod() {
return this.method;
}
@Override
public void setUserAttribute(String key, Object value) {
if (value != null) {
if (this.userAttributes == null) {
this.userAttributes = new HashMap<String, Object>();
}
this.userAttributes.put(key, value);
} else {
if (this.userAttributes != null) {
this.userAttributes.remove(key);
}
}
}
@Override
public Object getUserAttribute(String key) {
return (this.userAttributes != null ? this.userAttributes.get(key) : null);
}
}
support
package com.gator.spring.framework.aop.support;
import com.gator.spring.framework.aop.aspect.PABLO_AfterReturningAdviceInterceptor;
import com.gator.spring.framework.aop.aspect.PABLO_AfterThrowingAdviceInterceptor;
import com.gator.spring.framework.aop.aspect.PABLO_MethodBeforeAdviceInterceptor;
import com.gator.spring.framework.aop.config.PABLO_AopConfig;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PABLO_AdvisedSupport {
private Class<?> targetClass;
private Object target;
private PABLO_AopConfig config;
private Pattern pointCutClassPattern;
private transient Map<Method, List<Object>> methodCache;
public PABLO_AdvisedSupport(PABLO_AopConfig config) {
this.config = config;
}
public Class<?> getTargetClass() {
return this.targetClass;
}
public Object getTarget() {
return this.target;
}
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) throws Exception {
List<Object> cached = methodCache.get(method);
if (cached == null) {
Method m = targetClass.getMethod(method.getName(), method.getParameterTypes());
cached = methodCache.get(m);
this.methodCache.put(m, cached);
}
return cached;
}
public void setTargetClass(Class<?> targetClass) {
this.targetClass = targetClass;
parse();
}
private void parse() {
String pointCut = config.getPointCut()
.replaceAll("\\.", ".")
.replaceAll("\\\\.\\*", ".*")
.replaceAll("\\(", "\\\\(")
.replaceAll("\\)", "\\\\)");
String pointCutForClassRegex = pointCut.substring(0, pointCut.lastIndexOf("\\(") - 2);
pointCutClassPattern = Pattern.compile("class " + pointCutForClassRegex.substring(
pointCutForClassRegex.lastIndexOf(" ") + 1));
try {
methodCache = new HashMap<Method, List<Object>>();
Pattern pattern = Pattern.compile(pointCutForClassRegex);
Class aspectClass = Class.forName(this.config.getAspectClass());
Map<String, Method> aspectMethods = new HashMap<String, Method>();
for (Method m : aspectClass.getDeclaredMethods()) {
aspectMethods.put(m.getName(), m);
}
for (Method m : this.targetClass.getDeclaredMethods()) {
String methodString = m.toString();
if (methodString.contains("throws")) {
methodString = methodString.substring(0, methodString.lastIndexOf("throws")).trim();
}
Matcher matcher = pattern.matcher(methodString);
if (matcher.matches()) {
List<Object> advices = new LinkedList<Object>();
if (!(null == config.getAspectBefore() || "".equals(config.getAspectBefore()))) {
advices.add(new PABLO_MethodBeforeAdviceInterceptor(aspectMethods.get(config.getAspectBefore()), aspectClass.newInstance()));
}
if (!(null == config.getAspectAfter() || "".equals(config.getAspectAfter()))) {
advices.add(new PABLO_AfterReturningAdviceInterceptor(aspectMethods.get(config.getAspectAfter()), aspectClass.newInstance()));
}
if (!(null == config.getAspectAfterThrow() || "".equals(config.getAspectAfterThrow()))) {
PABLO_AfterThrowingAdviceInterceptor throwingAdvice =
new PABLO_AfterThrowingAdviceInterceptor(
aspectMethods.get(config.getAspectAfterThrow()),
aspectClass.newInstance());
throwingAdvice.setThrowName(config.getAspectAfterThrowingName());
advices.add(throwingAdvice);
}
methodCache.put(m, advices);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void setTarget(Object target) {
this.target = target;
}
public boolean pointCutMatch() {
return pointCutClassPattern.matcher(this.targetClass.toString()).matches();
}
}
public interface PABLO_AopProxy {
Object getProxy();
Object getProxy(ClassLoader classLoader);
}
import com.gator.spring.framework.aop.support.PABLO_AdvisedSupport;
public class PABLO_CglibAopProxy implements PABLO_AopProxy {
public PABLO_CglibAopProxy(PABLO_AdvisedSupport config) {
}
@Override
public Object getProxy() {
return null;
}
@Override
public Object getProxy(ClassLoader classLoader) {
return null;
}
}
package com.gator.spring.framework.aop;
import com.gator.spring.framework.aop.intercept.PABLO_MethodInvocation;
import com.gator.spring.framework.aop.support.PABLO_AdvisedSupport;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
public class PABLO_JdkDynamicAopProxy implements PABLO_AopProxy, InvocationHandler {
private PABLO_AdvisedSupport advised;
public PABLO_JdkDynamicAopProxy(PABLO_AdvisedSupport config) {
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());
PABLO_MethodInvocation invocation = new PABLO_MethodInvocation(proxy, this.advised.getTarget(), method, args, this.advised.getTargetClass(), chain);
return invocation.proceed();
}
}
beans
public class PABLO_BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception {
System.out.println( "-----"+beanName+"初始化对象之前");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws Exception {
System.out.println( "-----"+beanName+"初始化对象之后");
return bean;
}
}
@Data
public class PABLO_BeanDefinition {
private String beanClassName;
private String factoryBeanName;
private boolean lazyInit = false;
private boolean isSingleton = true;
}
package com.gator.spring.framework.beans.support;
import com.gator.spring.framework.beans.factory.config.PABLO_BeanDefinition;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class PABLO_BeanDefinitionReader {
private List<String> registryBeanClasses = new ArrayList<String>();
private Properties config = new Properties();
private final String SCAN_PACKAGE = "scanPackage";
public PABLO_BeanDefinitionReader(String... locations) {
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();
}
}
}
String property = config.getProperty(SCAN_PACKAGE);
for (String scanPackage : property.split(",")) {
doScanner(scanPackage);
}
}
private void doScanner(String scanPackage) {
URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));
File dir = new File(url.getFile());
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
doScanner(scanPackage + "." + file.getName());
} else {
registryBeanClasses.add(scanPackage + "." + file.getName().replace(".class", "").trim());
}
}
}
public Properties getConfig() {
return this.config;
}
public List<PABLO_BeanDefinition> loadBeanDefinitions() {
List<PABLO_BeanDefinition> result = new ArrayList<PABLO_BeanDefinition>();
try {
for (String className : registryBeanClasses) {
Class<?> beanClass = Class.forName(className);
if (beanClass.isInterface()) continue;
char c = beanClass.getSimpleName().toCharArray()[0];
result.add(doCreateBeanDefinition(Character.isLowerCase(c)
? beanClass.getSimpleName()
: toLowerFirstCase(beanClass.getSimpleName()),
beanClass.getName()));
result.add(doCreateBeanDefinition(beanClass.getName(), beanClass.getName()));
Class<?>[] interfaces = beanClass.getInterfaces();
for (Class<?> i : interfaces) {
result.add(doCreateBeanDefinition(i.getName(), beanClass.getName()));
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private PABLO_BeanDefinition doCreateBeanDefinition(String factoryBeanName, String beanClassName) {
PABLO_BeanDefinition beanDefinition = new PABLO_BeanDefinition();
beanDefinition.setBeanClassName(beanClassName);
beanDefinition.setFactoryBeanName(factoryBeanName);
return beanDefinition;
}
private String toLowerFirstCase(String simpleName) {
char[] chars = simpleName.toCharArray();
chars[0] += 32;
return String.valueOf(chars);
}
}
package com.gator.spring.framework.beans.support;
import com.gator.spring.framework.beans.factory.config.PABLO_BeanDefinition;
import com.gator.spring.framework.context.support.PABLO_AbstractApplicationContext;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class PABLO_DefaultListableBeanFactory
extends PABLO_AbstractApplicationContext {
public final Map<String, PABLO_BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, PABLO_BeanDefinition>(256);
@Override
public Object getBean(String beanName) throws Exception {
return null;
}
}
package com.gator.spring.framework.beans;
public class PABLO_BeanWrapper {
private Object wrappedInstance;
private Class<?> wrappedClass;
public PABLO_BeanWrapper(Object wrappedInstance){
this.wrappedInstance = wrappedInstance;
this.wrappedClass = wrappedInstance.getClass();
}
public Object getWrappedInstance(){
return this.wrappedInstance;
}
public Class<?> getWrappedClass(){
return this.wrappedClass;
}
@Override
public String toString() {
return "PABLO_BeanWrapper{" +
"wrappedInstance=" + wrappedInstance +
", wrappedClass=" + wrappedClass +
'}';
}
}
context
package com.gator.spring.framework.context.support;
import com.gator.spring.framework.core.PABLO_BeanFactory;
public abstract class PABLO_AbstractApplicationContext implements PABLO_BeanFactory {
protected void refresh() throws Exception {}
}
package com.gator.spring.framework.context;
import com.gator.spring.framework.annotation.PABLO_Autowired;
import com.gator.spring.framework.annotation.PABLO_Controller;
import com.gator.spring.framework.annotation.PABLO_Service;
import com.gator.spring.framework.aop.PABLO_AopProxy;
import com.gator.spring.framework.aop.PABLO_CglibAopProxy;
import com.gator.spring.framework.aop.PABLO_JdkDynamicAopProxy;
import com.gator.spring.framework.aop.config.PABLO_AopConfig;
import com.gator.spring.framework.aop.support.PABLO_AdvisedSupport;
import com.gator.spring.framework.beans.PABLO_BeanWrapper;
import com.gator.spring.framework.beans.config.PABLO_BeanPostProcessor;
import com.gator.spring.framework.beans.factory.config.PABLO_BeanDefinition;
import com.gator.spring.framework.beans.support.PABLO_BeanDefinitionReader;
import com.gator.spring.framework.beans.support.PABLO_DefaultListableBeanFactory;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
public class PABLO_ApplicationContext
extends PABLO_DefaultListableBeanFactory {
private String[] configLocations;
private PABLO_BeanDefinitionReader reader;
private Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>();
private Map<String, PABLO_BeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<String, PABLO_BeanWrapper>();
public PABLO_ApplicationContext(String... configLocations) {
this.configLocations = configLocations;
try {
refresh();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void refresh() throws Exception {
reader = new PABLO_BeanDefinitionReader(this.configLocations);
List<PABLO_BeanDefinition> beanDefinitions = reader.loadBeanDefinitions();
doRegisterBeanDefinition(beanDefinitions);
doAutowired();
}
private void doAutowired() {
for (Map.Entry<String, PABLO_BeanDefinition> beanDefinitionEntry : super.beanDefinitionMap.entrySet()) {
String beanName = beanDefinitionEntry.getKey();
if (!beanDefinitionEntry.getValue().isLazyInit()) {
try {
getBean(beanName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private void doRegisterBeanDefinition(List<PABLO_BeanDefinition> beanDefinitions) throws Exception {
for (PABLO_BeanDefinition beanDefinition : beanDefinitions) {
if (super.beanDefinitionMap.containsKey(beanDefinition.getFactoryBeanName())) {
throw new Exception("The “" + beanDefinition.getFactoryBeanName() + "” is exists!!");
}
super.beanDefinitionMap.put(beanDefinition.getFactoryBeanName(), beanDefinition);
}
}
public Object getBean(Class clazz) throws Exception {
return getBean(clazz.getName());
}
@Override
public Object getBean(String beanName) throws Exception {
if (this.singletonObjects.containsKey(beanName)) {
return this.singletonObjects.get(beanName);
}
PABLO_BeanDefinition pablo_beanDefinition = beanDefinitionMap.get(beanName);
Object instance = instantiateBean(beanName, pablo_beanDefinition);
PABLO_BeanWrapper beanWrapper = new PABLO_BeanWrapper(instance);
factoryBeanInstanceCache.put(beanName, beanWrapper);
PABLO_BeanPostProcessor postProcessor = new PABLO_BeanPostProcessor();
postProcessor.postProcessBeforeInitialization(instance, beanName);
populateBean(beanName, new PABLO_BeanDefinition(), beanWrapper);
postProcessor.postProcessAfterInitialization(instance, beanName);
return this.factoryBeanInstanceCache.get(beanName).getWrappedInstance();
}
private void populateBean(String beanName, PABLO_BeanDefinition pablo_beanDefinition, PABLO_BeanWrapper beanWrapper) {
Object instance = beanWrapper.getWrappedInstance();
Class<?> clazz = beanWrapper.getWrappedClass();
if (!(clazz.isAnnotationPresent(PABLO_Controller.class) || clazz.isAnnotationPresent(PABLO_Service.class)))
return;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (!field.isAnnotationPresent(PABLO_Autowired.class)) continue;
PABLO_Autowired autowired = field.getAnnotation(PABLO_Autowired.class);
String autowiredBeanName = autowired.value().trim();
if ("".equals(autowiredBeanName)) autowiredBeanName = field.getType().getName();
field.setAccessible(true);
try {
if (this.factoryBeanInstanceCache.get(autowiredBeanName) == null) {
continue;
}
field.set(instance, this.factoryBeanInstanceCache.get(autowiredBeanName).getWrappedInstance());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
private Object instantiateBean(String beanName, PABLO_BeanDefinition pablo_beanDefinition) {
Object instance = null;
try {
String className = pablo_beanDefinition.getBeanClassName();
Class<?> clazz = Class.forName(className);
instance = clazz.newInstance();
PABLO_AdvisedSupport advisedSupport = loadAopConfig();
advisedSupport.setTargetClass(clazz);
advisedSupport.setTarget(instance);
if (advisedSupport.pointCutMatch()) {
instance = createProxy(advisedSupport).getProxy();
}
this.singletonObjects.put(beanName, instance);
} catch (Exception e) {
e.printStackTrace();
}
return instance;
}
public String[] getBeanDefinitionNames() {
return this.beanDefinitionMap.keySet().toArray(new String[this.beanDefinitionMap.size()]);
}
public Properties getConfig() {
return this.reader.getConfig();
}
private PABLO_AopProxy createProxy(PABLO_AdvisedSupport config) {
Class targetClass = config.getTargetClass();
if (targetClass.getInterfaces().length > 0) {
return new PABLO_JdkDynamicAopProxy(config);
}
return new PABLO_CglibAopProxy(config);
}
private PABLO_AdvisedSupport loadAopConfig() {
PABLO_AopConfig config = new PABLO_AopConfig();
config.setPointCut(this.reader.getConfig().getProperty("pointCut"));
config.setAspectClass(this.reader.getConfig().getProperty("aspectClass"));
config.setAspectBefore(this.reader.getConfig().getProperty("aspectBefore"));
config.setAspectAfter(this.reader.getConfig().getProperty("aspectAfter"));
config.setAspectAfterThrow(this.reader.getConfig().getProperty("aspectAfterThrow"));
config.setAspectAfterThrowingName(this.reader.getConfig().getProperty("aspectAfterThrowingName"));
return new PABLO_AdvisedSupport(config);
}
}
package com.gator.spring.framework.context;
import org.springframework.beans.BeansException;
public interface PABLO_ApplicationContextAware {
void setApplicationContext(PABLO_ApplicationContext applicationContext) throws BeansException;
}
core
package com.gator.spring.framework.core;
public interface PABLO_BeanFactory {
Object getBean(String beanName) throws Exception;
}
package com.gator.spring.framework.core;
public interface PABLO_FactoryBean {
}
webmvc
package com.gator.spring.framework.webmvc.servlet;
import com.gator.spring.framework.annotation.PABLO_RequestParam;
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 PABLO_HandlerAdapter {
public boolean supports(Object handler){ return (handler instanceof PABLO_HandlerMapping);}
PABLO_ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
PABLO_HandlerMapping handlerMapping = (PABLO_HandlerMapping)handler;
Map<String,Integer> paramIndexMapping = new HashMap<String, Integer>();
Annotation[] [] pa = handlerMapping.getMethod().getParameterAnnotations();
for (int i = 0; i < pa.length ; i ++) {
for(Annotation a : pa[i]){
if(a instanceof PABLO_RequestParam){
String paramName = ((PABLO_RequestParam) a).value();
if(!"".equals(paramName.trim())){
paramIndexMapping.put(paramName, i);
}
}
}
}
Class<?> [] paramsTypes = handlerMapping.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 = handlerMapping.getMethod().invoke(handlerMapping.getController(),paramValues);
if(result == null || result instanceof Void){ return null; }
boolean isModelAndView = handlerMapping.getMethod().getReturnType() == PABLO_ModelAndView.class;
if(isModelAndView){
return (PABLO_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);
}else {
if(value != null){
return value;
}
return null;
}
}
}
package com.gator.spring.framework.webmvc.servlet;
import java.lang.reflect.Method;
import java.util.regex.Pattern;
public class PABLO_HandlerMapping {
private Object controller;
private Method method;
private Pattern pattern;
public PABLO_HandlerMapping(Pattern pattern, Object controller, Method method) {
this.controller = controller;
this.method = method;
this.pattern = pattern;
}
@Override
public String toString() {
return "PABLO_HandlerMapping{" +
"controller=" + controller +
", method=" + method +
", pattern=" + pattern +
'}';
}
public Object getController() {
return controller;
}
public void setController(Object controller) {
this.controller = controller;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
public Pattern getPattern() {
return pattern;
}
public void setPattern(Pattern pattern) {
this.pattern = pattern;
}
}
package com.gator.spring.framework.webmvc.servlet;
import java.util.Map;
public class PABLO_ModelAndView {
private String viewName;
private Map<String,?> model;
public PABLO_ModelAndView(String viewName) { this.viewName = viewName; }
public PABLO_ModelAndView(String viewName, Map<String, ?> model) {
this.viewName = viewName;
this.model = model;
}
public String getViewName() {
return viewName;
}
public Map<String, ?> getModel() {
return model;
}
}
package com.gator.spring.framework.webmvc.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PABLO_View {
public final String DEFAULT_CONTENT_TYPE = "text/html;charset=utf-8";
public final String CHARACTER_ENCODING = "UTF-8";
private File viewFile;
public PABLO_View(File viewFile) {
this.viewFile = viewFile;
}
public void render(Map<String, ?> model,
HttpServletRequest request, HttpServletResponse response) throws Exception{
StringBuffer sb = new StringBuffer();
RandomAccessFile ra = new RandomAccessFile(this.viewFile,"r");
String line = null;
while (null != (line = ra.readLine())){
line = new String(line.getBytes("ISO-8859-1"),"utf-8");
Pattern pattern = Pattern.compile("¥\\{[^\\}]+\\}",Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(line);
while (matcher.find()){
String paramName = matcher.group();
paramName = paramName.replaceAll("¥\\{|\\}","");
Object paramValue = model.get(paramName);
if(null == paramValue){ continue;}
line = matcher.replaceFirst(makeStringForRegExp(paramValue.toString()));
matcher = pattern.matcher(line);
}
sb.append(line);
}
response.setCharacterEncoding(CHARACTER_ENCODING);
response.getWriter().write(sb.toString());
}
public static String makeStringForRegExp(String str) {
return str.replace("\\", "\\\\").replace("*", "\\*")
.replace("+", "\\+").replace("|", "\\|")
.replace("{", "\\{").replace("}", "\\}")
.replace("(", "\\(").replace(")", "\\)")
.replace("^", "\\^").replace("$", "\\$")
.replace("[", "\\[").replace("]", "\\]")
.replace("?", "\\?").replace(",", "\\,")
.replace(".", "\\.").replace("&", "\\&");
}
}
package com.gator.spring.framework.webmvc.servlet;
import java.io.File;
import java.util.Locale;
public class PABLO_ViewResolver {
private final String DEFAULT_TEMPLATE_SUFFIX = ".html";
private File templateRootDir;
public PABLO_ViewResolver(String templateRoot) {
String templateRootPath = this.getClass().getClassLoader().getResource(templateRoot).getFile();
templateRootDir = new File(templateRootPath);
}
public PABLO_View resolveViewName(String viewName, Locale locale) throws Exception{
if(null == viewName || "".equals(viewName.trim())){return null;}
viewName = viewName.endsWith(DEFAULT_TEMPLATE_SUFFIX) ? viewName : (viewName + DEFAULT_TEMPLATE_SUFFIX);
File templateFile = new File((templateRootDir.getPath() + "/" + viewName).replaceAll("/+","/"));
return new PABLO_View(templateFile);
}
}
package com.gator.spring.framework.webmvc.servlet;
import com.gator.spring.framework.annotation.PABLO_Controller;
import com.gator.spring.framework.annotation.PABLO_RequestMapping;
import com.gator.spring.framework.context.PABLO_ApplicationContext;
import lombok.extern.slf4j.Slf4j;
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.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Slf4j
public class PABO_DispatcherServlet extends HttpServlet {
private final String CONTEXT_CONFIG_LOCATION = "contextConfigLocation";
private PABLO_ApplicationContext context;
private List<PABLO_HandlerMapping> handlerMappings = new ArrayList<>();
private Map<PABLO_HandlerMapping, PABLO_HandlerAdapter> handlerAdapters = new HashMap<PABLO_HandlerMapping, PABLO_HandlerAdapter>();
private List<PABLO_ViewResolver> viewResolvers = new ArrayList<PABLO_ViewResolver>();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
this.doDispatch(req, resp);
} catch (Exception e) {
try {
processDispatchResult(req, resp, new PABLO_ModelAndView("500"));
} catch (Exception ex) {
ex.printStackTrace();
}
e.printStackTrace();
}
}
@Override
public void init(ServletConfig config) throws ServletException {
context = new PABLO_ApplicationContext(config.getInitParameter(CONTEXT_CONFIG_LOCATION));
initStrategies(context);
}
private void initStrategies(PABLO_ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
private void initHandlerAdapters(PABLO_ApplicationContext context) {
for (PABLO_HandlerMapping handlerMapping : this.handlerMappings) {
this.handlerAdapters.put(handlerMapping, new PABLO_HandlerAdapter());
}
}
private void initViewResolvers(PABLO_ApplicationContext context) {
String templateRoot = context.getConfig().getProperty("templateRoot");
String templateRootPath = this.getClass().getClassLoader().getResource(templateRoot).getFile();
File templateRootDir = new File(templateRootPath);
String[] templates = templateRootDir.list();
for (int i = 0; i < templates.length; i++) {
this.viewResolvers.add(new PABLO_ViewResolver(templateRoot));
}
}
private void initRequestToViewNameTranslator(PABLO_ApplicationContext context) {
}
private void initHandlerExceptionResolvers(PABLO_ApplicationContext context) {
}
private void initFlashMapManager(PABLO_ApplicationContext context) {
}
private void initHandlerMappings(PABLO_ApplicationContext context) {
String[] beanNames = context.getBeanDefinitionNames();
try {
for (String beanName : beanNames) {
Object controller = context.getBean(beanName);
Class<?> clazz = controller.getClass();
if (!clazz.isAnnotationPresent(PABLO_Controller.class)) continue;
String baseUrl = "";
if (clazz.isAnnotationPresent(PABLO_RequestMapping.class)) {
PABLO_RequestMapping requestMapping = clazz.getAnnotation(PABLO_RequestMapping.class);
baseUrl = requestMapping.value();
}
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (!method.isAnnotationPresent(PABLO_RequestMapping.class)) continue;
PABLO_RequestMapping requestMapping = method.getAnnotation(PABLO_RequestMapping.class);
String regex = ("/" + baseUrl + "/" + requestMapping.value().replaceAll("\\*", ".*")).replaceAll("/+", "/");
Pattern pattern = Pattern.compile(regex);
this.handlerMappings.add(new PABLO_HandlerMapping(pattern, controller, method));
}
}
handlerMappings = removeDuplicate(handlerMappings);
System.out.println("------------Mapper info------------");
handlerMappings.forEach(PABLO_HandlerMapping->
System.out.print("Controller->"+PABLO_HandlerMapping.getController().getClass().getSimpleName()+" url->"+PABLO_HandlerMapping.getPattern().pattern()+ " \n")
);
} catch (Exception e) {
e.printStackTrace();
}
}
private List<PABLO_HandlerMapping> removeDuplicate(List<PABLO_HandlerMapping> handlerMappings) {
Set<PABLO_HandlerMapping> distance = new TreeSet<>(new Comparator<PABLO_HandlerMapping>() {
@Override
public int compare(PABLO_HandlerMapping o1, PABLO_HandlerMapping o2) {
return o1.getPattern().pattern().compareTo(o2.getPattern().pattern());
}
});
distance.addAll(handlerMappings);
return new ArrayList<>(distance);
}
private void initThemeResolver(PABLO_ApplicationContext context) {
}
private void initLocaleResolver(PABLO_ApplicationContext context) {
}
private void initMultipartResolver(PABLO_ApplicationContext context) {
}
private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {
PABLO_HandlerMapping handler = getHandler(req);
if (Objects.isNull(handler)) {
processDispatchResult(req, resp, new PABLO_ModelAndView("404"));
return;
}
PABLO_HandlerAdapter ha = getHandlerAdapter(handler);
PABLO_ModelAndView mv = ha.handle(req, resp, handler);
processDispatchResult(req, resp, mv);
}
private PABLO_HandlerAdapter getHandlerAdapter(PABLO_HandlerMapping handler) {
if (this.handlerAdapters.isEmpty()) {
return null;
}
PABLO_HandlerAdapter ha = this.handlerAdapters.get(handler);
if (ha.supports(handler)) return ha;
return null;
}
private void processDispatchResult(HttpServletRequest req, HttpServletResponse resp, PABLO_ModelAndView mv) throws Exception {
if (Objects.isNull(mv)) return;
if (this.viewResolvers.isEmpty()) return;
for (PABLO_ViewResolver viewResolver : this.viewResolvers) {
PABLO_View view = viewResolver.resolveViewName(mv.getViewName(), null);
view.render(mv.getModel(), req, resp);
return;
}
}
private PABLO_HandlerMapping getHandler(HttpServletRequest req) {
if (this.handlerMappings.isEmpty()) return null;
String url = req.getRequestURI();
String contextPath = req.getContextPath();
url = url.replace(contextPath, "").replaceAll("/+", "/");
for (PABLO_HandlerMapping handler : this.handlerMappings) {
try {
Matcher matcher = handler.getPattern().matcher(url);
if (!matcher.matches()) {
continue;
}
return handler;
} catch (Exception e) {
throw e;
}
}
return null;
}
}
|