├── .gitignore ├── README.md ├── commons ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── tg │ │ └── tiny4j │ │ └── commons │ │ ├── constants │ │ ├── ConfigurationElement.java │ │ ├── HttpMethod.java │ │ └── WebApplicationEnvironment.java │ │ ├── data │ │ └── Pair.java │ │ └── utils │ │ ├── ClassUtil.java │ │ ├── JsonUtil.java │ │ └── Validate.java │ └── test │ └── com │ └── tg │ └── tiny4j │ └── commons │ └── utils │ ├── ClassUtilTest.java │ └── SampleBean.java ├── core ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── tg │ │ │ └── tiny4j │ │ │ └── core │ │ │ ├── aop │ │ │ ├── AbstractAopProxy.java │ │ │ ├── AopProxy.java │ │ │ ├── AutoSetterCglibAopProxy.java │ │ │ ├── CglibAopProxy.java │ │ │ ├── JdkDynamicAopProxy.java │ │ │ ├── README.txt │ │ │ ├── advice │ │ │ │ ├── AopAdvice.java │ │ │ │ ├── AopInterceptor.java │ │ │ │ ├── AutoSetterCglibMethodinvocation.java │ │ │ │ ├── BeanAnnotatedAopInterceptor.java │ │ │ │ ├── CglibMethodinvocation.java │ │ │ │ ├── Invocation.java │ │ │ │ ├── JoinPointtest.java │ │ │ │ ├── Methodinvocation.java │ │ │ │ └── Target.java │ │ │ └── exception │ │ │ │ └── AdviceDefinitionException.java │ │ │ ├── ioc │ │ │ ├── annotation │ │ │ │ ├── Bean.java │ │ │ │ ├── Component.java │ │ │ │ ├── Configuration.java │ │ │ │ ├── Inject.java │ │ │ │ └── Value.java │ │ │ ├── beans │ │ │ │ ├── BeanAnnotatedDefinition.java │ │ │ │ ├── BeanDefinition.java │ │ │ │ ├── BeanPostProcessor.java │ │ │ │ ├── BeanPropertyValue.java │ │ │ │ ├── BeanReference.java │ │ │ │ ├── factory │ │ │ │ │ ├── AbstractBeanFactory.java │ │ │ │ │ ├── BeanFactory.java │ │ │ │ │ └── DefaultBeanFactory.java │ │ │ │ └── reader │ │ │ │ │ ├── AbstractBeanDefinitionReader.java │ │ │ │ │ ├── AnnotationBeanDefinitionReader.java │ │ │ │ │ ├── AutoConfigBeanDefinitionReader.java │ │ │ │ │ ├── BeanDefinitionReader.java │ │ │ │ │ ├── ClassScanner.java │ │ │ │ │ ├── PackageChecker.java │ │ │ │ │ ├── PlaceholderPraser.java │ │ │ │ │ └── XmlBeanDefinitionReader.java │ │ │ ├── context │ │ │ │ ├── AbstractApplicationContext.java │ │ │ │ ├── ApplicationContext.java │ │ │ │ ├── ApplicationContextHolder.java │ │ │ │ └── ClassPathXmlApplicationContext.java │ │ │ ├── exception │ │ │ │ ├── BeanDefinitionException.java │ │ │ │ ├── BeanException.java │ │ │ │ ├── ConfigurationException.java │ │ │ │ └── PropertyDuplicateException.java │ │ │ └── resource │ │ │ │ ├── Resource.java │ │ │ │ ├── ResourceLoad.java │ │ │ │ └── UrlResource.java │ │ │ └── web │ │ │ └── integration │ │ │ ├── BootAppBeanDefinitionReader.java │ │ │ ├── ContextListener │ │ │ ├── AbstractBootContextListener.java │ │ │ └── AbstractWebContextListener.java │ │ │ ├── HandleAnnotation.java │ │ │ ├── HandleRegistry.java │ │ │ ├── WebAppBeanDefinitionReader.java │ │ │ └── context │ │ │ ├── BootApplicationContext.java │ │ │ ├── ServletContainerApplicationContext.java │ │ │ └── WebApplicationContext.java │ └── resources │ │ ├── application.properties │ │ └── log4j2.xml │ └── test │ ├── java │ └── com │ │ └── tg │ │ └── tiny4j │ │ └── core │ │ ├── aop │ │ ├── Add.java │ │ ├── AddOperate.java │ │ ├── CglibDynamicAopProxyTest.java │ │ ├── JdkDynamicAopProxyTest.java │ │ ├── Operate.java │ │ └── TestAopInterceptor.java │ │ └── ioc │ │ ├── beans │ │ └── reader │ │ │ ├── ConfigBean.java │ │ │ ├── DaoBean.java │ │ │ ├── LogBeanPostProcessor.java │ │ │ ├── ServiceBean.java │ │ │ └── XmlBeanDefinitionReaderTest.java │ │ ├── context │ │ └── ClassPathXmlApplicationContextTest.java │ │ └── resource │ │ └── ResourceLoadTest.java │ └── resources │ ├── application.properties │ ├── log4j2.xml │ └── test.xml ├── pom.xml ├── rest ├── README.md ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── tg │ └── tiny4j │ └── web │ ├── annotation │ ├── Api.java │ ├── CROS.java │ ├── ComponentScan.java │ ├── ExceptionHandler.java │ ├── Interceptor.java │ ├── InterceptorExclude.java │ ├── InterceptorInclude.java │ ├── InterceptorSelect.java │ ├── PathVariable.java │ ├── RequestBody.java │ ├── RequestMapping.java │ └── RequestParam.java │ ├── contextlistener │ └── SingleRestLoaderListener.java │ ├── exception │ ├── ConfigurationException.java │ ├── ExceptionHandleException.java │ ├── InterceptorDuplicatedException.java │ └── UrlDuplicatedException.java │ ├── handle │ └── RequestHandleMapping.java │ ├── integration │ └── WebAppControllerReader.java │ ├── interceptor │ └── HandlerInterceptor.java │ ├── jettyembed │ ├── Configuration.java │ └── TinyApplication.java │ ├── metadata │ ├── BaseInfo.java │ ├── ControllerInfo.java │ ├── CrosInfo.java │ ├── ExceptionHandleInfo.java │ ├── InterceptorInfo.java │ ├── RequestHandleInfo.java │ ├── RequestMapper.java │ └── UrlPraseInfo.java │ ├── reader │ ├── AbstractClassReader.java │ ├── ClassScanner.java │ ├── ConfigLoader.java │ ├── Reader.java │ └── WebScanedClassReader.java │ └── servlet │ └── DispatcherServlet.java ├── web-containerembed ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── tg │ │ │ └── web │ │ │ ├── Application.java │ │ │ ├── contextlistener │ │ │ └── BootAppLoaderListener.java │ │ │ ├── controller │ │ │ ├── AInterceptor.java │ │ │ ├── BInterceptor.java │ │ │ ├── BaseController.java │ │ │ ├── TestController.java │ │ │ ├── TestException.java │ │ │ └── TestServlet.java │ │ │ ├── dao │ │ │ └── UserDao.java │ │ │ ├── model │ │ │ └── User.java │ │ │ └── service │ │ │ └── UserService.java │ └── resources │ │ ├── application.properties │ │ └── log4j2.xml │ └── test │ └── java │ └── com │ └── tg │ └── embed │ ├── JetttyTest.java │ └── TomcatTest.java └── web-test ├── pom.xml └── src └── main ├── java └── com │ └── tg │ └── web │ ├── contextlistener │ └── WebAppLoaderListener.java │ ├── controller │ ├── AInterceptor.java │ ├── BInterceptor.java │ ├── BaseController.java │ ├── TestController.java │ ├── TestException.java │ └── TestServlet.java │ ├── dao │ └── UserDao.java │ ├── model │ └── User.java │ └── service │ └── UserService.java ├── resources ├── application.properties ├── application.xml └── log4j2.xml └── webapp ├── WEB-INF └── web.xml └── index.jsp /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | **/target/ 3 | /logs/ 4 | /.settings/ 5 | /.classpath 6 | /.DS_Store 7 | /.project 8 | /.idea/ 9 | /*.iml 10 | *.iml 11 | /inte -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tiny4j 2 | 会点java,做点web,基本也就是spring全家桶,都是IOC,AOP,MVC这样的概念,所以打算自己折腾一个,实现最基本最常用的一些功能。 3 | ### IOC 4 | 简单使用如下: 5 | 6 | ``` 7 | ApplicationContext applicationContext = new ClassPathXmlApplicationContext("test.xml"); 8 | ServiceBean serviceBean=(ServiceBean)applicationContext.getBean("testService"); 9 | System.out.println(serviceBean); 10 | serviceBean.service(); 11 | 12 | ServiceBean serviceBean2=(ServiceBean)applicationContext.getBean("serviceBean"); 13 | System.out.println(serviceBean2); 14 | serviceBean2.service(); 15 | 16 | //全局的容器上下文 17 | ApplicationContextHolder holder=applicationContext.getBean("applicationContextHolder", ApplicationContextHolder.class); 18 | System.out.println("holder get bean : "+holder.getBean("serviceBean")); 19 | ``` 20 | [详细说明](https://github.com/twogoods/tiny4j/tree/master/core) 21 | ### rest 22 | 不多说直接上controller代码 23 | 24 | ``` 25 | @Api("/base") 26 | public class TestController extends BaseController { 27 | 28 | @Value("${user.name:test}") 29 | private String name; 30 | 31 | @Inject 32 | private UserService userService; 33 | 34 | @RequestMapping 35 | public String index() { 36 | userService.query(); 37 | return name; 38 | } 39 | 40 | @RequestMapping(mapUrl = "/test/{id}", method = HttpMethod.GET) 41 | @CROS(origins = "www.baidu.com", methods = {HttpMethod.GET}, maxAge = "3600") 42 | public String patgTest(@PathVariable("id") String id) { 43 | return id; 44 | } 45 | 46 | @RequestMapping(mapUrl = "/test", method = HttpMethod.GET) 47 | @InterceptorSelect(include = {"aInterceptor"}, exclude = {"bInterceptor"}) 48 | public String interceptorTest() { 49 | return "haha"; 50 | } 51 | 52 | 53 | @RequestMapping(mapUrl = "/index") 54 | @CROS 55 | public String paramTest(@RequestParam("id") long id, @RequestParam("name") String name) { 56 | return name + "---" + id; 57 | } 58 | 59 | @RequestMapping(mapUrl = "/user/{id}", method = HttpMethod.PUT) 60 | @CROS 61 | public User insert(@PathVariable("id") long id, @RequestBody User user) { 62 | return user; 63 | } 64 | } 65 | ``` 66 | 是不是感觉很熟悉,SpringMvc既视感... 67 | **现已支持SpringBoot风格的可执行jar**,请看[详细说明](https://github.com/twogoods/tiny4j/tree/master/rest) 68 | 69 | TODO 70 | 71 | * 反射优化 72 | 73 | ### AOP 74 | TODO 75 | -------------------------------------------------------------------------------- /commons/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | tiny4j 7 | com.twogoods.tiny4j 8 | 0.0.1 9 | 10 | 4.0.0 11 | 12 | commons 13 | 14 | 15 | 16 | com.alibaba 17 | fastjson 18 | 1.1.46 19 | 20 | 21 | org.apache.commons 22 | commons-io 23 | 1.3.2 24 | 25 | 26 | org.apache.commons 27 | commons-lang3 28 | 3.4 29 | 30 | 31 | commons-validator 32 | commons-validator 33 | 1.3.1 34 | 35 | 36 | commons-codec 37 | commons-codec 38 | 1.9 39 | 40 | 41 | com.google.guava 42 | guava 43 | 19.0 44 | 45 | 46 | javax.servlet 47 | javax.servlet-api 48 | 4.0.0-b03 49 | 50 | 51 | org.aspectj 52 | aspectjweaver 53 | 1.8.9 54 | 55 | 56 | cglib 57 | cglib 58 | 3.2.4 59 | 60 | 61 | com.esotericsoftware 62 | reflectasm 63 | 1.11.3 64 | 65 | 66 | 67 | 68 | 69 | 70 | org.apache.maven.plugins 71 | maven-surefire-plugin 72 | 73 | true 74 | 75 | 76 | 77 | org.apache.maven.plugins 78 | maven-compiler-plugin 79 | 3.1 80 | 81 | 1.7 82 | 1.7 83 | UTF-8 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /commons/src/main/java/com/tg/tiny4j/commons/constants/ConfigurationElement.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.commons.constants; 2 | 3 | /** 4 | * Description: 5 | * 6 | * @author twogoods 7 | * @version 0.1 8 | * @since 2017-03-13 9 | */ 10 | public class ConfigurationElement { 11 | 12 | public static final String COMPONENTSCAN = "tiny4j.component-scan"; 13 | public static final String SERVER_CONTEXTPATH = "tiny4j.server.contextPath"; 14 | public static final String SERVER_PORT = "tiny4j.server.port"; 15 | 16 | public static final String DEFAULT_CONFIG_FILE = "application.properties"; 17 | } 18 | -------------------------------------------------------------------------------- /commons/src/main/java/com/tg/tiny4j/commons/constants/HttpMethod.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.commons.constants; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | 5 | /** 6 | * Created by twogoods on 16/11/7. 7 | */ 8 | public class HttpMethod { 9 | public static final String GET = "GET"; 10 | public static final String POST = "POST"; 11 | public static final String PUT = "PUT"; 12 | public static final String DELETE = "DELETE"; 13 | //jdk7- not support 14 | public static final String PATCH = "PATCH"; 15 | //cors 16 | public static final String OPTIONS = "OPTIONS"; 17 | //not filter 18 | public static final String HEAD = "HEAD"; 19 | 20 | 21 | public static boolean support(String httpMethod) { 22 | if(StringUtils.isEmpty(httpMethod)){ 23 | return true; 24 | } 25 | return GET.equals(httpMethod) || POST.equals(httpMethod) || PUT.equals(httpMethod) 26 | || DELETE.equals(httpMethod) || PATCH.equals(httpMethod); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /commons/src/main/java/com/tg/tiny4j/commons/constants/WebApplicationEnvironment.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.commons.constants; 2 | 3 | /** 4 | * Created by twogoods on 16/11/5. 5 | */ 6 | public class WebApplicationEnvironment { 7 | public static final String RUN_MODE="run_mode"; 8 | public static final String SINGLE_MODE="single"; 9 | public static final String CONTAINER_MODE="container"; 10 | 11 | public static final String WEBREQUESTMAPPER="webrequestmapper"; 12 | public static final String ROOT_APPLICATION="root_applicationcontext"; 13 | 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /commons/src/main/java/com/tg/tiny4j/commons/data/Pair.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.commons.data; 2 | 3 | /** 4 | * Created by twogoods on 16/10/29. 5 | */ 6 | public class Pair { 7 | private L l; 8 | private R r; 9 | 10 | private Pair(L l, R r) { 11 | this.l = l; 12 | this.r = r; 13 | } 14 | 15 | public static Pair of(L left, R right){ 16 | return new Pair(left,right); 17 | } 18 | 19 | public L getL() { 20 | return l; 21 | } 22 | 23 | public void setL(L l) { 24 | this.l = l; 25 | } 26 | 27 | public R getR() { 28 | return r; 29 | } 30 | 31 | public void setR(R r) { 32 | this.r = r; 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return "Pair{" + 38 | "l=" + l + 39 | ", r=" + r + 40 | '}'; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /commons/src/main/java/com/tg/tiny4j/commons/utils/ClassUtil.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.commons.utils; 2 | /** 3 | * Description: 4 | * 5 | * @author twogoods 6 | * @version 0.1 7 | * @since 2017-04-04 8 | */ 9 | public class ClassUtil { 10 | 11 | 12 | } 13 | -------------------------------------------------------------------------------- /commons/src/main/java/com/tg/tiny4j/commons/utils/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.commons.utils; 2 | import com.alibaba.fastjson.JSON; 3 | import com.alibaba.fastjson.TypeReference; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | import java.io.Writer; 11 | import java.util.Map; 12 | /** 13 | * Created by twogoods on 16/12/1. 14 | */ 15 | public class JsonUtil { 16 | 17 | private static final Logger log = LoggerFactory.getLogger(JsonUtil.class); 18 | 19 | public static String jsonFromObject(Object object) { 20 | String str; 21 | try { 22 | str = JSON.toJSONString(object); 23 | } catch (RuntimeException e) { 24 | throw e; 25 | } catch (Exception e) { 26 | log.error("Unable to serialize to json: " + object, e); 27 | return null; 28 | } 29 | return str; 30 | } 31 | 32 | public static String jsonFromObject(Object object, String dateFormat) { 33 | String str; 34 | try { 35 | str = JSON.toJSONStringWithDateFormat(object, dateFormat); 36 | } catch (RuntimeException e) { 37 | throw e; 38 | } catch (Exception e) { 39 | log.error("Unable to serialize to json: " + object, e); 40 | return null; 41 | } 42 | return str; 43 | } 44 | 45 | public static T objectFromJson(String json, Class klass) { 46 | T object; 47 | try { 48 | object = JSON.parseObject(json, klass); 49 | } catch (RuntimeException e) { 50 | log.error("Runtime exception during deserializing " + klass.getSimpleName() + " from " 51 | + StringUtils.abbreviate(json, 80)); 52 | throw e; 53 | } catch (Exception e) { 54 | log.error("Exception during deserializing " + klass.getSimpleName() + " from " 55 | + StringUtils.abbreviate(json, 80)); 56 | return null; 57 | } 58 | return object; 59 | } 60 | 61 | public static T objectFromJson(String json, TypeReference klass) { 62 | T object; 63 | try { 64 | object = JSON.parseObject(json, klass); 65 | } catch (RuntimeException e) { 66 | log.error("Runtime exception during deserializing from " + StringUtils.abbreviate(json, 80)); 67 | throw e; 68 | } catch (Exception e) { 69 | e.printStackTrace(); 70 | log.error("Exception during deserializing from " + StringUtils.abbreviate(json, 80)); 71 | return null; 72 | } 73 | return object; 74 | } 75 | 76 | public static Map toMap(String jsonString) { 77 | return JSON.parseObject(jsonString); 78 | } 79 | 80 | public static void writeValue(Writer writer, Object value) { 81 | JSON.writeJSONStringTo(value, writer); 82 | } 83 | 84 | public static void writeValue(HttpServletResponse response,Object value) throws IOException{ 85 | response.setHeader("Content-Type", "application/json;charset=utf-8"); 86 | JSON.writeJSONStringTo(value, response.getWriter()); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /commons/src/main/java/com/tg/tiny4j/commons/utils/Validate.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.commons.utils; 2 | 3 | import java.util.List; 4 | import java.util.Set; 5 | 6 | /** 7 | * Created by twogoods on 16/10/26. 8 | */ 9 | public class Validate { 10 | public static boolean isEmpty(Object obj){ 11 | if(obj==null||"".equals(obj)){ 12 | return true; 13 | } 14 | return false; 15 | } 16 | 17 | public static boolean isEmpty(List list){ 18 | if(list==null||list.size()==0){ 19 | return true; 20 | } 21 | return false; 22 | } 23 | public static boolean isEmpty(Set set){ 24 | if(set==null||set.size()==0){ 25 | return true; 26 | } 27 | return false; 28 | } 29 | public static boolean isEmpty(Object[] strArr){ 30 | if(strArr==null||strArr.length==0){ 31 | return true; 32 | } 33 | return false; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /commons/src/test/com/tg/tiny4j/commons/utils/ClassUtilTest.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.commons.utils; 2 | 3 | import com.esotericsoftware.reflectasm.MethodAccess; 4 | import net.sf.cglib.reflect.FastClass; 5 | import net.sf.cglib.reflect.FastMethod; 6 | import net.sf.cglib.reflect.MethodDelegate; 7 | import org.junit.Test; 8 | 9 | import java.lang.reflect.Method; 10 | 11 | /** 12 | * Description: 13 | * 14 | * @author twogoods 15 | * @version 0.1 16 | * @since 2017-04-04 17 | */ 18 | public class ClassUtilTest { 19 | public interface BeanDelegate { 20 | String getValueFromDelegate(String s); 21 | } 22 | 23 | @Test 24 | public void testMethodDelegate() throws Exception { 25 | SampleBean bean = new SampleBean(); 26 | bean.setValue("Hello cglib!"); 27 | //将SampleBean的getValue方法 绑定到接口的方法 28 | BeanDelegate delegate = (BeanDelegate) MethodDelegate.create(bean, "echo", BeanDelegate.class); 29 | System.out.println(delegate.getValueFromDelegate("twogoods")); 30 | } 31 | 32 | @Test 33 | public void testFastClass() throws Exception { 34 | FastClass fastClass = FastClass.create(SampleBean.class); 35 | FastMethod fastMethod = fastClass.getMethod(SampleBean.class.getMethod("echo", String.class, int.class)); 36 | SampleBean myBean = new SampleBean(); 37 | myBean.setValue("Hello cglib!"); 38 | long start = System.currentTimeMillis(); 39 | for (int i = 0; i < 1000000; i++) { 40 | fastMethod.invoke(myBean, new Object[]{"haha" + i, 12}); 41 | } 42 | System.out.println("cglib:" + (System.currentTimeMillis() - start)); 43 | 44 | start = System.currentTimeMillis(); 45 | Method m = SampleBean.class.getMethod("echo", String.class, int.class); 46 | for (int i = 0; i < 1000000; i++) { 47 | m.invoke(myBean, "haha" + i, 12); 48 | } 49 | System.out.println("reflect:" + (System.currentTimeMillis() - start)); 50 | 51 | start = System.currentTimeMillis(); 52 | for (int i = 0; i < 1000000; i++) { 53 | myBean.echo("haha" + i, 12); 54 | } 55 | System.out.println("normal:" + (System.currentTimeMillis() - start)); 56 | 57 | MethodAccess access = MethodAccess.get(SampleBean.class); 58 | start = System.currentTimeMillis(); 59 | for (int i = 0; i < 1000000; i++) { 60 | access.invoke(myBean, "echo", "haha" + i, 12); 61 | } 62 | System.out.println("ReflectASM:" + (System.currentTimeMillis() - start)); 63 | } 64 | } -------------------------------------------------------------------------------- /commons/src/test/com/tg/tiny4j/commons/utils/SampleBean.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.commons.utils; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * Description: 9 | * 10 | * @author twogoods 11 | * @version 0.1 12 | * @since 2017-04-04 13 | */ 14 | public class SampleBean { 15 | private String value; 16 | 17 | public SampleBean() { 18 | } 19 | 20 | public SampleBean(String value) { 21 | this.value = value; 22 | } 23 | 24 | public String getValue() { 25 | return value; 26 | } 27 | 28 | public void setValue(String value) { 29 | this.value = value; 30 | } 31 | 32 | public String echo(String name, int age) { 33 | // List names = new ArrayList<>(100); 34 | // for (int i = 0; i < 100; i++) { 35 | // names.add(name + i); 36 | // } 37 | // List ages = new ArrayList<>(100); 38 | // for (int i = 0; i < 100; i++) { 39 | // ages.add(age + i); 40 | // } 41 | return name + "--" + age; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /core/README.md: -------------------------------------------------------------------------------- 1 | ##IOC 2 | 基于xml配置的方式 3 | 4 | ``` 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ``` 19 | 编程方式使用: 20 | 21 | ``` 22 | ApplicationContext applicationContext = new ClassPathXmlApplicationContext("test.xml"); 23 | ServiceBean serviceBean=(ServiceBean)applicationContext.getBean("testService"); 24 | System.out.println(serviceBean); 25 | serviceBean.service(); 26 | 27 | ServiceBean serviceBean2=(ServiceBean)applicationContext.getBean("serviceBean"); 28 | System.out.println(serviceBean2); 29 | serviceBean2.service(); 30 | ``` 31 | 当然你也可以添加配置文件,并配置component-scan属性来自动扫描包下的类 32 | 33 | ``` 34 | 35 | 36 | 37 | application.properties 38 | ${tiny4j.component-scan:com.tg} 39 | 40 | 41 | 42 | 43 | ``` 44 | 只要配置好扫描的包完全可以只使用注解 45 | 46 | ``` 47 | @Configuration 48 | public class ConfigBean { 49 | 50 | @Value("${user.name:testname}") 51 | private String name; 52 | @Value("${user.pass}") 53 | private String pass; 54 | 55 | @Inject 56 | private ServiceBean serviceBean; 57 | 58 | //创建的bean的名字就是方法名 59 | @Bean 60 | public DaoBean beanAnnDao(){ 61 | return new DaoBean(); 62 | } 63 | @Bean 64 | public ServiceBean beanAnnService(){ 65 | //new ServiceBean(beanAnnDao()); 暂不支持构造器注入 66 | ServiceBean newBean=new ServiceBean(); 67 | newBean.setS1(name+"---"+serviceBean.getS1()); 68 | newBean.setS2(pass+"---"+serviceBean.getS2()); 69 | newBean.setDaoBean(beanAnnDao()); 70 | return newBean; 71 | } 72 | 73 | } 74 | ``` 75 | 76 | -------------------------------------------------------------------------------- /core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | tiny4j 7 | com.twogoods.tiny4j 8 | 0.0.1 9 | 10 | 4.0.0 11 | 12 | core 13 | 14 | 15 | com.twogoods.tiny4j 16 | commons 17 | 0.0.1 18 | 19 | 20 | org.aspectj 21 | aspectjweaver 22 | 1.8.9 23 | 24 | 25 | cglib 26 | cglib 27 | 3.2.4 28 | 29 | 30 | 31 | 32 | 33 | 34 | org.apache.maven.plugins 35 | maven-surefire-plugin 36 | 37 | true 38 | 39 | 40 | 41 | org.apache.maven.plugins 42 | maven-compiler-plugin 43 | 3.1 44 | 45 | 1.7 46 | 1.7 47 | UTF-8 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/AbstractAopProxy.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop; 2 | 3 | import com.tg.tiny4j.core.aop.advice.AopAdvice; 4 | import com.tg.tiny4j.core.aop.exception.AdviceDefinitionException; 5 | 6 | /** 7 | * Created by twogoods on 16/10/24. 8 | */ 9 | public abstract class AbstractAopProxy implements AopProxy{ 10 | 11 | protected AopAdvice aopAdvice; 12 | 13 | public AbstractAopProxy(AopAdvice aopAdvice) { 14 | this.aopAdvice = aopAdvice; 15 | } 16 | 17 | public void checkAopAdvice() throws AdviceDefinitionException { 18 | if(aopAdvice.getTarget()==null){ 19 | throw new AdviceDefinitionException("AopAdvice's target can't be null"); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/AopProxy.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop; 2 | 3 | import com.tg.tiny4j.core.aop.exception.AdviceDefinitionException; 4 | 5 | /** 6 | * Created by twogoods on 16/10/24. 7 | */ 8 | public interface AopProxy { 9 | Object getProxy() throws AdviceDefinitionException; 10 | } 11 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/AutoSetterCglibAopProxy.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop; 2 | 3 | import com.tg.tiny4j.core.aop.advice.AopAdvice; 4 | import com.tg.tiny4j.core.aop.advice.AutoSetterCglibMethodinvocation; 5 | import com.tg.tiny4j.core.aop.exception.AdviceDefinitionException; 6 | import net.sf.cglib.core.Signature; 7 | import net.sf.cglib.proxy.InterfaceMaker; 8 | import net.sf.cglib.proxy.MethodProxy; 9 | import org.apache.commons.lang3.text.WordUtils; 10 | import org.objectweb.asm.Type; 11 | 12 | import java.lang.reflect.Field; 13 | import java.lang.reflect.Method; 14 | import java.util.HashMap; 15 | import java.util.Map; 16 | 17 | /** 18 | * Created by twogoods on 16/10/31. 19 | */ 20 | public class AutoSetterCglibAopProxy extends CglibAopProxy{ 21 | 22 | private Map autoSetter=new HashMap<>(); 23 | 24 | public AutoSetterCglibAopProxy(AopAdvice aopAdvice) { 25 | super(aopAdvice); 26 | } 27 | 28 | @Override 29 | public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 30 | if (aopAdvice.getInterceptor() == null) { 31 | return methodProxy.invokeSuper(o, objects); 32 | } else { 33 | return aopAdvice.getInterceptor().invoke(new AutoSetterCglibMethodinvocation(o, method, objects, methodProxy,aopAdvice.getTarget().getClazz(),autoSetter)); 34 | } 35 | } 36 | 37 | private Class createSetter() { 38 | Class objCla = aopAdvice.getTarget().getClazz(); 39 | Field[] fields = objCla.getDeclaredFields(); 40 | InterfaceMaker im = new InterfaceMaker(); 41 | for (Field f : fields) { 42 | String setterName = "set" + WordUtils.capitalize(f.getName()); 43 | try { 44 | objCla.getDeclaredMethod(setterName,f.getType()); 45 | } catch (NoSuchMethodException e) { 46 | im.add(new Signature(setterName, Type.VOID_TYPE,new Type[]{Type.getType(f.getType())}), null); 47 | autoSetter.put(setterName,setterName); 48 | } 49 | } 50 | return im.create(); 51 | } 52 | 53 | @Override 54 | public Object getProxy() throws AdviceDefinitionException { 55 | checkAopAdvice(); 56 | enhancer.setSuperclass(aopAdvice.getTarget().getClazz()); 57 | enhancer.setInterfaces(new Class[]{createSetter()}); 58 | enhancer.setCallback(this); 59 | return enhancer.create(); 60 | } 61 | 62 | public Map getAutoSetter() { 63 | return autoSetter; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/CglibAopProxy.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop; 2 | 3 | import com.tg.tiny4j.core.aop.advice.AopAdvice; 4 | import com.tg.tiny4j.core.aop.advice.CglibMethodinvocation; 5 | import com.tg.tiny4j.core.aop.exception.AdviceDefinitionException; 6 | import net.sf.cglib.proxy.Enhancer; 7 | import net.sf.cglib.proxy.MethodInterceptor; 8 | import net.sf.cglib.proxy.MethodProxy; 9 | 10 | import java.lang.reflect.Method; 11 | 12 | /** 13 | * Created by twogoods on 16/10/24. 14 | */ 15 | public class CglibAopProxy extends AbstractAopProxy implements MethodInterceptor { 16 | protected Enhancer enhancer = new Enhancer(); 17 | 18 | public CglibAopProxy(AopAdvice aopAdvice) { 19 | super(aopAdvice); 20 | } 21 | 22 | @Override 23 | public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 24 | if (aopAdvice.getInterceptor() == null) { 25 | return methodProxy.invokeSuper(o, objects); 26 | } else { 27 | return aopAdvice.getInterceptor().invoke(new CglibMethodinvocation(o, method, objects, methodProxy,aopAdvice.getTarget().getClazz())); 28 | } 29 | } 30 | 31 | @Override 32 | public Object getProxy() throws AdviceDefinitionException { 33 | checkAopAdvice(); 34 | enhancer.setSuperclass(aopAdvice.getTarget().getClazz()); 35 | enhancer.setCallback(this); 36 | return enhancer.create(); 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/JdkDynamicAopProxy.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop; 2 | 3 | import com.tg.tiny4j.commons.utils.Validate; 4 | import com.tg.tiny4j.core.aop.advice.AopAdvice; 5 | import com.tg.tiny4j.core.aop.advice.Methodinvocation; 6 | import com.tg.tiny4j.core.aop.exception.AdviceDefinitionException; 7 | 8 | import java.lang.reflect.InvocationHandler; 9 | import java.lang.reflect.Method; 10 | import java.lang.reflect.Proxy; 11 | 12 | /** 13 | * Created by twogoods on 16/10/24. 14 | */ 15 | public class JdkDynamicAopProxy extends AbstractAopProxy implements InvocationHandler { 16 | 17 | public JdkDynamicAopProxy(AopAdvice aopAdvice) { 18 | super(aopAdvice); 19 | } 20 | 21 | @Override 22 | public Object getProxy() throws AdviceDefinitionException { 23 | checkAopAdvice(); 24 | return Proxy.newProxyInstance(getClass().getClassLoader(), aopAdvice.getTarget().getInterfaceClazz(), this); 25 | } 26 | 27 | @Override 28 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 29 | if (aopAdvice.getInterceptor() == null) { 30 | return method.invoke(aopAdvice.getTarget().getTargetObj(), args); 31 | } else { 32 | return aopAdvice.getInterceptor().invoke(new Methodinvocation(aopAdvice.getTarget().getTargetObj(), method, args)); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/README.txt: -------------------------------------------------------------------------------- 1 | 切面(Aspect): 横切关注点(跨越应用程序多个模块的功能)被模块化的特殊对象 2 | 通知(Advice): 切面必须要完成的工作 3 | 目标(Target): 被通知的对象 4 | 代理(Proxy): 向目标对象应用通知之后创建的对象 5 | 连接点(Joinpoint):程序执行的某个特定位置:如类某个方法调用前、调用后、方法抛出异常后等。 6 | 连接点由两个信息确定:方法表示的程序执行点;相对点表示的方位。例如 ArithmethicCalculator#add() 方法执行前的连接点, 7 | 执行点为 ArithmethicCalculator#add(); 方位为该方法执行前的位置 8 | 切点(pointcut):每个类都拥有多个连接点.AOP 通过切点定位到特定的连接点。类比:连接点相当于数据库中的记录,切点相当于查询条件。 9 | 切点和连接点不是一对一的关系,一个切点匹配多个连接点. -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/advice/AopAdvice.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop.advice; 2 | 3 | /** 4 | * Created by twogoods on 16/10/25. 5 | */ 6 | public class AopAdvice { 7 | private Target target; 8 | private AopInterceptor interceptor; 9 | 10 | public Target getTarget() { 11 | return target; 12 | } 13 | 14 | public void setTarget(Target target) { 15 | this.target = target; 16 | } 17 | 18 | public AopInterceptor getInterceptor() { 19 | return interceptor; 20 | } 21 | 22 | public void setInterceptor(AopInterceptor interceptor) { 23 | this.interceptor = interceptor; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/advice/AopInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop.advice; 2 | 3 | /** 4 | * Created by twogoods on 16/10/24. 5 | */ 6 | public interface AopInterceptor { 7 | 8 | Object invoke(Methodinvocation invocation) throws Throwable; 9 | 10 | } 11 | 12 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/advice/AutoSetterCglibMethodinvocation.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop.advice; 2 | 3 | import net.sf.cglib.proxy.MethodProxy; 4 | 5 | import java.lang.reflect.Method; 6 | import java.util.Map; 7 | 8 | /** 9 | * Created by twogoods on 16/10/31. 10 | */ 11 | public class AutoSetterCglibMethodinvocation extends CglibMethodinvocation { 12 | private Map autoSetter; 13 | 14 | public AutoSetterCglibMethodinvocation(Object target, Method method, Object[] args, MethodProxy methodProxy, Map autoSetter) { 15 | super(target, method, args, methodProxy); 16 | this.autoSetter = autoSetter; 17 | } 18 | 19 | public AutoSetterCglibMethodinvocation(Object target, Method method, Object[] args, MethodProxy methodProxy, Class clazz, Map autoSetter) { 20 | super(target, method, args, methodProxy, clazz); 21 | this.autoSetter = autoSetter; 22 | } 23 | 24 | public Map getAutoSetter() { 25 | return autoSetter; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/advice/BeanAnnotatedAopInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop.advice; 2 | 3 | import com.tg.tiny4j.commons.utils.Validate; 4 | import com.tg.tiny4j.core.ioc.beans.BeanDefinition; 5 | import com.tg.tiny4j.core.ioc.beans.factory.BeanFactory; 6 | import org.apache.commons.lang3.text.WordUtils; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import java.lang.reflect.Field; 11 | import java.util.Map; 12 | 13 | /** 14 | * Created by twogoods on 16/10/30. 15 | */ 16 | 17 | public class BeanAnnotatedAopInterceptor implements AopInterceptor { 18 | private static final Logger log = LoggerFactory.getLogger(BeanAnnotatedAopInterceptor.class); 19 | 20 | private Map methodsMap; 21 | 22 | Map beans; 23 | 24 | private BeanFactory beanFactory; 25 | 26 | 27 | public BeanAnnotatedAopInterceptor(Map methodInfos, BeanFactory beanFactory) { 28 | this.methodsMap = methodInfos; 29 | this.beanFactory = beanFactory; 30 | } 31 | 32 | public BeanAnnotatedAopInterceptor(Map methodsMap, Map beans, BeanFactory beanFactory) { 33 | this.methodsMap = methodsMap; 34 | this.beans = beans; 35 | this.beanFactory = beanFactory; 36 | } 37 | 38 | public BeanAnnotatedAopInterceptor(Map methodsMap, Map beans) { 39 | this.methodsMap = methodsMap; 40 | this.beans = beans; 41 | } 42 | 43 | @Override 44 | public Object invoke(Methodinvocation invocation) throws Throwable { 45 | String methodName = invocation.getMethod().getName(); 46 | if (invocation instanceof AutoSetterCglibMethodinvocation) { 47 | Map autoSetter = ((AutoSetterCglibMethodinvocation) invocation).getAutoSetter(); 48 | if (!Validate.isEmpty(autoSetter.get(methodName))) { 49 | log.debug("do setter method:{} ", methodName); 50 | Field f = invocation.getObjClass().getDeclaredField(getFieldNameBySetter(methodName)); 51 | f.setAccessible(true); 52 | f.set(invocation.getTarget(), invocation.getArguments()[0]); 53 | return null; 54 | } 55 | } 56 | if (methodsMap.containsKey(methodName)) { 57 | log.debug("interceptor the @Bean method:{}", methodName); 58 | Object bean = beans.get(methodsMap.get(methodName)).getBean(); 59 | if (bean == null) { 60 | //这里是调用用户方法创建的一个对象,放回容器 61 | Object obj = invocation.proceed(); 62 | beans.get(methodsMap.get(methodName)).setBean(obj); 63 | return obj; 64 | } 65 | return bean; 66 | } 67 | return invocation.proceed(); 68 | } 69 | 70 | private String getFieldNameBySetter(String setterName) { 71 | return WordUtils.uncapitalize(setterName.substring("set".length())); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/advice/CglibMethodinvocation.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop.advice; 2 | 3 | import net.sf.cglib.proxy.MethodProxy; 4 | 5 | import java.lang.reflect.Method; 6 | 7 | /** 8 | * Created by twogoods on 16/10/25. 9 | */ 10 | public class CglibMethodinvocation extends Methodinvocation{ 11 | private MethodProxy methodProxy; 12 | private Class clazz; 13 | 14 | public CglibMethodinvocation(Object target, Method method, Object[] args,MethodProxy methodProxy) { 15 | super(target, method, args); 16 | this.methodProxy=methodProxy; 17 | } 18 | 19 | public CglibMethodinvocation(Object target, Method method, Object[] args, MethodProxy methodProxy, Class clazz) { 20 | super(target, method, args,clazz); 21 | this.methodProxy = methodProxy; 22 | } 23 | 24 | @Override 25 | public Object proceed() throws Throwable { 26 | return methodProxy.invokeSuper(target,args); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/advice/Invocation.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop.advice; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | 6 | /** 7 | * Created by twogoods on 16/10/24. 8 | */ 9 | interface Invocation { 10 | Object proceed() throws Throwable; 11 | 12 | Object getTarget(); 13 | 14 | Object[] getArguments(); 15 | 16 | Method getMethod(); 17 | 18 | Class getObjClass(); 19 | 20 | } 21 | 22 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/advice/JoinPointtest.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop.advice; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | /** 6 | * Created by twogoods on 16/10/24. 7 | */ 8 | public class JoinPointtest implements Invocation{ 9 | private Object target; 10 | private Method method; 11 | private Object[] args; 12 | private Class objClass; 13 | 14 | public JoinPointtest(Object target, Method method, Object[] args) { 15 | this.target = target; 16 | this.method = method; 17 | this.args = args; 18 | } 19 | 20 | @Override 21 | public Object proceed() throws Throwable{ 22 | return method.invoke(target,args); 23 | } 24 | 25 | @Override 26 | public Object getTarget() { 27 | return target; 28 | } 29 | 30 | @Override 31 | public Object[] getArguments() { 32 | return args; 33 | } 34 | 35 | @Override 36 | public Method getMethod() { 37 | return method; 38 | } 39 | 40 | @Override 41 | public Class getObjClass() { 42 | return objClass; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/advice/Methodinvocation.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop.advice; 2 | 3 | 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * Created by twogoods on 16/10/24. 8 | */ 9 | public class Methodinvocation implements Invocation { 10 | 11 | protected Object target; 12 | protected Method method; 13 | protected Object[] args; 14 | protected Class objClass; 15 | 16 | public Methodinvocation(Object target, Method method, Object[] args) { 17 | this.target = target; 18 | this.method = method; 19 | this.args = args; 20 | } 21 | 22 | public Methodinvocation(Object target, Method method, Object[] args, Class objClass) { 23 | this.target = target; 24 | this.method = method; 25 | this.args = args; 26 | this.objClass = objClass; 27 | } 28 | 29 | @Override 30 | public Object proceed() throws Throwable { 31 | return method.invoke(target, args); 32 | } 33 | 34 | @Override 35 | public Object getTarget() { 36 | return target; 37 | } 38 | 39 | @Override 40 | public Object[] getArguments() { 41 | return args; 42 | } 43 | 44 | @Override 45 | public Method getMethod() { 46 | return method; 47 | } 48 | 49 | @Override 50 | public Class getObjClass() { 51 | return objClass; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/advice/Target.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop.advice; 2 | 3 | /** 4 | * Created by twogoods on 16/10/25. 5 | */ 6 | public class Target { 7 | private Object targetObj; 8 | private Class clazz; 9 | private Class[] interfaceClazz; 10 | 11 | public Target(Object target, Class clazz, Class[] interfaceClazz) { 12 | this.targetObj = target; 13 | this.clazz = clazz; 14 | this.interfaceClazz = interfaceClazz; 15 | } 16 | 17 | public Target(Class clazz) { 18 | this.clazz = clazz; 19 | } 20 | 21 | public Object getTargetObj() { 22 | return targetObj; 23 | } 24 | 25 | public void setTargetObj(Object targetObj) { 26 | this.targetObj = targetObj; 27 | } 28 | 29 | public Class getClazz() { 30 | return clazz; 31 | } 32 | 33 | public void setClazz(Class clazz) { 34 | this.clazz = clazz; 35 | } 36 | 37 | public Class[] getInterfaceClazz() { 38 | return interfaceClazz; 39 | } 40 | 41 | public void setInterfaceClazz(Class[] interfaceClazz) { 42 | this.interfaceClazz = interfaceClazz; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/aop/exception/AdviceDefinitionException.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop.exception; 2 | 3 | /** 4 | * Created by twogoods on 16/10/25. 5 | */ 6 | public class AdviceDefinitionException extends Exception { 7 | public AdviceDefinitionException(String message) { 8 | super(message); 9 | } 10 | 11 | public AdviceDefinitionException(String message, Throwable cause) { 12 | super(message, cause); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/annotation/Bean.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by twogoods on 16/10/27. 10 | */ 11 | @Target({ElementType.METHOD}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface Bean { 14 | String name() default ""; 15 | } 16 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/annotation/Component.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by twogoods on 16/10/27. 10 | */ 11 | @Target({ElementType.TYPE,ElementType.ANNOTATION_TYPE}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface Component { 14 | String name() default ""; 15 | } 16 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/annotation/Configuration.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by twogoods on 16/10/27. 10 | */ 11 | @Target({ElementType.TYPE}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Component 14 | public @interface Configuration { 15 | String name()default ""; 16 | } 17 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/annotation/Inject.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by twogoods on 16/10/27. 10 | */ 11 | @Target({ElementType.FIELD}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface Inject { 14 | String name() default ""; 15 | } 16 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/annotation/Value.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by twogoods on 16/10/27. 10 | */ 11 | @Target({ElementType.FIELD}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface Value { 14 | String value(); 15 | } 16 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/BeanAnnotatedDefinition.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans; 2 | 3 | import com.tg.tiny4j.core.aop.advice.AopAdvice; 4 | import com.tg.tiny4j.core.aop.advice.AopInterceptor; 5 | import com.tg.tiny4j.core.aop.advice.Methodinvocation; 6 | 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | /** 12 | * Created by twogoods on 16/10/30. 13 | */ 14 | public class BeanAnnotatedDefinition extends BeanDefinition{ 15 | public BeanAnnotatedDefinition(String id, String classname) throws ClassNotFoundException { 16 | super(id, classname); 17 | } 18 | 19 | public BeanAnnotatedDefinition(String id, Class clazz) { 20 | super(id, clazz); 21 | } 22 | 23 | private Map methodInfos=new HashMap<>(); 24 | 25 | private AopAdvice aopAdvice; 26 | 27 | public void putmethodInfo(String methodName,String beanName) { 28 | methodInfos.put(methodName,beanName); 29 | } 30 | public void putmethodInfos(Map infos) { 31 | methodInfos.putAll(infos); 32 | } 33 | 34 | public Map getMethodInfos() { 35 | return methodInfos; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/BeanDefinition.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans; 2 | 3 | import com.tg.tiny4j.core.ioc.exception.PropertyDuplicateException; 4 | 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | 8 | /** 9 | * Created by twogoods on 16/10/26. 10 | */ 11 | public class BeanDefinition { 12 | private Object bean; 13 | private String id; 14 | private String classname; 15 | private Class clazz; 16 | private Set properties=new HashSet(); 17 | 18 | public BeanDefinition() {} 19 | 20 | public BeanDefinition(String id, String classname) throws ClassNotFoundException { 21 | this.id = id; 22 | this.classname = classname; 23 | clazz=Class.forName(classname); 24 | } 25 | 26 | public BeanDefinition(String id, String classname, Class clazz) { 27 | this.id = id; 28 | this.classname = classname; 29 | this.clazz = clazz; 30 | } 31 | 32 | public BeanDefinition(String id, Class clazz) { 33 | this.id = id; 34 | this.clazz = clazz; 35 | this.classname=clazz.getCanonicalName(); 36 | } 37 | 38 | public void addProperty(BeanPropertyValue beanProperty) throws PropertyDuplicateException { 39 | if (properties.contains(beanProperty)) { 40 | throw new PropertyDuplicateException(String.format("class:%s , property '%s' is duplicate",classname,beanProperty.getName())); 41 | } 42 | properties.add(beanProperty); 43 | } 44 | 45 | public Set getProperties() { 46 | return properties; 47 | } 48 | 49 | public String getId() { 50 | return id; 51 | } 52 | 53 | public String getClassname() { 54 | return classname; 55 | } 56 | 57 | public Object getBean() { 58 | return bean; 59 | } 60 | 61 | public void setBean(Object bean) { 62 | this.bean = bean; 63 | } 64 | 65 | public Class getClazz() { 66 | return clazz; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/BeanPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans; 2 | 3 | /** 4 | * Created by twogoods on 16/10/26. 5 | */ 6 | public interface BeanPostProcessor { 7 | Object postProcessBeforeInitialization(Object bean, String beanName); 8 | 9 | Object postProcessAfterInitialization(Object bean, String beanName); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/BeanPropertyValue.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans; 2 | 3 | import java.util.Objects; 4 | 5 | /** 6 | * Created by twogoods on 16/10/26. 7 | */ 8 | public class BeanPropertyValue { 9 | private String name; 10 | private Object value; 11 | 12 | public BeanPropertyValue() { 13 | } 14 | 15 | public BeanPropertyValue(String name, Object value) { 16 | this.name = name; 17 | this.value = value; 18 | } 19 | 20 | public String getName() { 21 | return name; 22 | } 23 | 24 | public void setName(String name) { 25 | this.name = name; 26 | } 27 | 28 | public Object getValue() { 29 | return value; 30 | } 31 | 32 | public void setValue(Object value) { 33 | this.value = value; 34 | } 35 | 36 | public boolean equals(Object o) { 37 | if (this == o) return true; 38 | if (o == null || getClass() != o.getClass()) return false; 39 | BeanPropertyValue that = (BeanPropertyValue) o; 40 | return Objects.equals(name, that.name); 41 | } 42 | 43 | @Override 44 | public int hashCode() { 45 | return Objects.hash(name); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/BeanReference.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans; 2 | 3 | /** 4 | * Created by twogoods on 16/10/26. 5 | */ 6 | public class BeanReference { 7 | private String name; 8 | private Object bean; 9 | 10 | public BeanReference() { 11 | } 12 | 13 | public BeanReference(String ref) { 14 | this.name = ref; 15 | } 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | public void setName(String name) { 22 | this.name = name; 23 | } 24 | 25 | public Object getBean() { 26 | return bean; 27 | } 28 | 29 | public void setBean(Object bean) { 30 | this.bean = bean; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/factory/AbstractBeanFactory.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.factory; 2 | 3 | import com.tg.tiny4j.commons.utils.Validate; 4 | import com.tg.tiny4j.core.aop.AopProxy; 5 | import com.tg.tiny4j.core.aop.AutoSetterCglibAopProxy; 6 | import com.tg.tiny4j.core.aop.advice.AopAdvice; 7 | import com.tg.tiny4j.core.aop.advice.BeanAnnotatedAopInterceptor; 8 | import com.tg.tiny4j.core.aop.advice.Target; 9 | import com.tg.tiny4j.core.ioc.beans.*; 10 | import com.tg.tiny4j.core.ioc.exception.BeanException; 11 | import org.apache.commons.lang3.text.WordUtils; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | import java.lang.reflect.Field; 16 | import java.lang.reflect.Method; 17 | import java.util.*; 18 | 19 | /** 20 | * Created by twogoods on 16/10/25. 21 | */ 22 | public abstract class AbstractBeanFactory implements BeanFactory { 23 | 24 | private static Logger log = LoggerFactory.getLogger(AbstractBeanFactory.class); 25 | 26 | private Map beans = new HashMap<>(); 27 | 28 | private List postProcessorList = new ArrayList<>(); 29 | 30 | private void selectBeanPostProcessor() throws Exception { 31 | if (postProcessorList.size() == 0) { 32 | log.debug("beans :{}", beans); 33 | for (String beanName : beans.keySet()) { 34 | String classname = beans.get(beanName).getClassname(); 35 | if (BeanPostProcessor.class.isAssignableFrom(Class.forName(classname))) { 36 | postProcessorList.add((BeanPostProcessor) getBean(beanName)); 37 | } 38 | } 39 | } 40 | } 41 | 42 | public void preInstantiateSingletons() throws Exception { 43 | selectBeanPostProcessor(); 44 | for (Iterator it = beans.keySet().iterator(); it.hasNext(); ) { 45 | String beanName = (String) it.next(); 46 | getBean(beanName); 47 | } 48 | } 49 | 50 | private Object createBeanAnnotatedBean(BeanAnnotatedDefinition beanAnnotatedDefinition) throws Exception { 51 | /** 52 | * 1.创建一个普通对象,把属性都赋好值 53 | * 2.设置aopadvice 54 | * 3.创建cglib代理对象 55 | * 4.为这个代理对象附上1中得到对象的属性值 56 | * 5.调用这个代理对象的方法,aop的拦截器里会调真正的那个方法,创建第一个对象出来,这个时候把这个对象放到容器里 57 | */ 58 | Object obj = createBean(beanAnnotatedDefinition); 59 | 60 | AopAdvice beanAnnotatedAopAdvice = new AopAdvice(); 61 | beanAnnotatedAopAdvice.setTarget(new Target(beanAnnotatedDefinition.getClazz())); 62 | beanAnnotatedAopAdvice.setInterceptor(new BeanAnnotatedAopInterceptor(beanAnnotatedDefinition.getMethodInfos(),beans, this)); 63 | 64 | AopProxy aopProxy = new AutoSetterCglibAopProxy(beanAnnotatedAopAdvice); 65 | Object proxyObj = aopProxy.getProxy(); 66 | 67 | Class proxyClass = proxyObj.getClass(); 68 | Field[] fields = obj.getClass().getDeclaredFields(); 69 | for (Field f : fields) { 70 | try { 71 | f.setAccessible(true); 72 | Method setter = proxyClass.getDeclaredMethod(getSetterName(f.getName()), f.getType()); 73 | setter.invoke(proxyObj, f.get(obj)); 74 | } catch (NoSuchMethodException e) { 75 | log.warn(e.getMessage()); 76 | } 77 | } 78 | Map annotatedMethods = beanAnnotatedDefinition.getMethodInfos(); 79 | log.debug("bean have @Bean method:{}",annotatedMethods); 80 | for (String methodName : annotatedMethods.keySet()) { 81 | proxyClass.getDeclaredMethod(methodName).invoke(proxyObj); 82 | } 83 | return proxyObj; 84 | } 85 | 86 | private String getSetterName(String fieldName) { 87 | return "set" + WordUtils.capitalize(fieldName); 88 | } 89 | 90 | @Override 91 | public Object getBean(String name) throws Exception { 92 | BeanDefinition beanDefinition = beans.get(name); 93 | if (Validate.isEmpty(beanDefinition)) { 94 | throw new BeanException(String.format("no bean named %s is define", name)); 95 | } 96 | Object bean = beanDefinition.getBean(); 97 | if (Validate.isEmpty(bean)) { 98 | if (beanDefinition instanceof BeanAnnotatedDefinition) { 99 | bean= createBeanAnnotatedBean((BeanAnnotatedDefinition) beanDefinition); 100 | bean = postProcess(bean, name); 101 | beanDefinition.setBean(bean); 102 | } else { 103 | bean = createBean(beans.get(name)); 104 | bean = postProcess(bean, name); 105 | beanDefinition.setBean(bean); 106 | } 107 | } 108 | return bean; 109 | } 110 | 111 | private Object postProcess(Object bean, String name) { 112 | for (BeanPostProcessor postProcessor : postProcessorList) { 113 | bean = postProcessor.postProcessBeforeInitialization(bean, name); 114 | } 115 | //spring 的bean配置里有一个initmetod,会在这里执行,此处略过 116 | for (BeanPostProcessor postProcessor : postProcessorList) { 117 | bean = postProcessor.postProcessAfterInitialization(bean, name); 118 | } 119 | return bean; 120 | } 121 | 122 | private Object createBean(BeanDefinition beanDefinition) throws Exception { 123 | //TODO 不支持构造函数设置属性值 124 | Object o = beanDefinition.getClazz().newInstance(); 125 | applyValue(o, beanDefinition); 126 | return o; 127 | } 128 | 129 | private void applyValue(Object bean, BeanDefinition beanDefinition) throws Exception { 130 | Set properties = beanDefinition.getProperties(); 131 | Iterator iterator = properties.iterator(); 132 | while (iterator.hasNext()) { 133 | BeanPropertyValue propertyValue = iterator.next(); 134 | String propertyName = propertyValue.getName(); 135 | Object value = propertyValue.getValue(); 136 | if (value instanceof BeanReference) { 137 | BeanReference beanReference = (BeanReference) value; 138 | value = getBean(beanReference.getName()); 139 | } 140 | try { 141 | /* 142 | TODO 类型转化,现在只能string 143 | Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName()); 144 | // int 为 Interger.type 145 | Class type=declaredField.getType(); 146 | declaredField.setAccessible(true); 147 | declaredField.set(bean, value); 148 | */ 149 | 150 | Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName()); 151 | declaredField.setAccessible(true); 152 | declaredField.set(bean, value); 153 | } catch (NoSuchFieldException e) { 154 | Method declaredMethod = bean.getClass().getDeclaredMethod( 155 | "set" + WordUtils.capitalize(propertyValue.getName()), value.getClass()); 156 | declaredMethod.setAccessible(true); 157 | } 158 | } 159 | 160 | } 161 | 162 | public void addPostProcessorList(BeanPostProcessor beanPostProcessor) { 163 | postProcessorList.add(beanPostProcessor); 164 | } 165 | 166 | public void addBeanDefinition(String name, BeanDefinition beanDefinition) { 167 | beans.put(name, beanDefinition); 168 | } 169 | 170 | public void addBeanDefinition(Map beanDefinitionMap) { 171 | beans.putAll(beanDefinitionMap); 172 | } 173 | 174 | @Override 175 | public T getBean(String name, Class clazz) throws Exception { 176 | Object bean = getBean(name); 177 | if (bean.getClass().equals(clazz)) { 178 | return (T) bean; 179 | } 180 | log.warn("bean:{},type:{} can not find", name, clazz); 181 | return null; 182 | } 183 | 184 | @Override 185 | public boolean containsBean(String name) throws Exception { 186 | return !Validate.isEmpty(getBean(name)); 187 | } 188 | 189 | 190 | } 191 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/factory/BeanFactory.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.factory; 2 | 3 | /** 4 | * Created by twogoods on 16/10/25. 5 | */ 6 | public interface BeanFactory { 7 | Object getBean(String name) throws Exception; 8 | 9 | T getBean(String name, Class clazz) throws Exception; 10 | 11 | boolean containsBean(String name) throws Exception; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/factory/DefaultBeanFactory.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.factory; 2 | 3 | /** 4 | * Created by twogoods on 16/10/25. 5 | */ 6 | public class DefaultBeanFactory extends AbstractBeanFactory{ 7 | 8 | public DefaultBeanFactory() {} 9 | } 10 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/reader/AbstractBeanDefinitionReader.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.reader; 2 | 3 | import com.tg.tiny4j.core.ioc.beans.BeanDefinition; 4 | import com.tg.tiny4j.core.ioc.exception.ConfigurationException; 5 | import com.tg.tiny4j.core.ioc.resource.ResourceLoad; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.apache.commons.lang3.text.WordUtils; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.util.*; 12 | 13 | /** 14 | * Created by twogoods on 16/10/26. 15 | */ 16 | public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader { 17 | private static final Logger log = LoggerFactory.getLogger(AbstractBeanDefinitionReader.class); 18 | 19 | private Map registerBeans; 20 | 21 | private Map configMap; 22 | 23 | public AbstractBeanDefinitionReader() { 24 | registerBeans = new HashMap<>(); 25 | configMap = new HashMap<>(); 26 | } 27 | 28 | public void loadConfig(String filePath) throws Exception { 29 | Properties prop = null; 30 | try { 31 | prop = ResourceLoad.getInstance().loadConfig(filePath); 32 | Enumeration en = prop.propertyNames(); 33 | while (en.hasMoreElements()) { 34 | String strKey = (String) en.nextElement(); 35 | configMap.put(strKey, prop.getProperty(strKey)); 36 | log.debug("get config : {} = {}", strKey, prop.getProperty(strKey)); 37 | } 38 | } catch (ConfigurationException e) { 39 | log.warn(e.getMessage()); 40 | } catch (Exception e1) { 41 | throw e1; 42 | } 43 | } 44 | 45 | @Override 46 | public Map getRegisterBeans() { 47 | return registerBeans; 48 | } 49 | 50 | 51 | protected String getConfigValue(PlaceholderPraser.KeyAndDefault valueAndDefault) { 52 | String value = configMap.get(valueAndDefault.getName()); 53 | if (value == null) { 54 | return valueAndDefault.getDefaultValue(); 55 | } 56 | return value; 57 | } 58 | 59 | protected String getConfigValue(String element) { 60 | return configMap.get(element); 61 | } 62 | 63 | /** 64 | * 通过全类名得到bean名 65 | * 66 | * @param classname 67 | * @return 68 | */ 69 | protected static String getBeanNameByClassName(String classname) { 70 | String[] path = classname.split("\\."); 71 | return WordUtils.uncapitalize(path[path.length - 1]); 72 | } 73 | 74 | /** 75 | * 未写注解参数,类名首字母小写 76 | */ 77 | protected String getBeanName(String annotName, Class clazz) { 78 | if (StringUtils.isEmpty(annotName)) { 79 | return WordUtils.uncapitalize(clazz.getSimpleName()); 80 | } 81 | return annotName; 82 | } 83 | 84 | protected String getBeanName(String annotName, String defaultName) { 85 | if (StringUtils.isEmpty(annotName)) { 86 | return WordUtils.uncapitalize(defaultName); 87 | } 88 | return annotName; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/reader/AnnotationBeanDefinitionReader.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.reader; 2 | 3 | import com.tg.tiny4j.core.ioc.beans.BeanAnnotatedDefinition; 4 | import com.tg.tiny4j.core.ioc.beans.BeanDefinition; 5 | import com.tg.tiny4j.core.ioc.beans.BeanPropertyValue; 6 | import com.tg.tiny4j.core.ioc.beans.BeanReference; 7 | import com.tg.tiny4j.core.ioc.exception.BeanDefinitionException; 8 | import com.tg.tiny4j.core.ioc.annotation.*; 9 | import com.tg.tiny4j.commons.data.Pair; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | import java.lang.annotation.Annotation; 14 | import java.lang.reflect.Field; 15 | import java.lang.reflect.Method; 16 | import java.util.*; 17 | 18 | /** 19 | * Created by twogoods on 16/10/26. 20 | */ 21 | public abstract class AnnotationBeanDefinitionReader extends AbstractBeanDefinitionReader { 22 | private static Logger log = LoggerFactory.getLogger(AnnotationBeanDefinitionReader.class); 23 | 24 | private List scanPackages = new ArrayList<>(); 25 | 26 | private Set classSet = new HashSet<>(); 27 | 28 | public AnnotationBeanDefinitionReader() { 29 | } 30 | 31 | public AnnotationBeanDefinitionReader(List scanPackages) { 32 | this.scanPackages = scanPackages; 33 | } 34 | 35 | @Override 36 | public void loadResource() throws Exception { 37 | Set classes = ClassScanner.getClasses(scanPackages); 38 | loadClasses(classes); 39 | praseAutoConfigurationClass(); 40 | } 41 | 42 | private void loadClasses(Set classes) throws ClassNotFoundException { 43 | for (String className : classes) { 44 | classSet.add(Class.forName(className)); 45 | } 46 | } 47 | 48 | private void praseAutoConfigurationClass() throws Exception { 49 | for (Class clazz : classSet) { 50 | Pair result = checkBeanAnnotated(clazz); 51 | if (result.getL() && result.getR()) { 52 | praseBeanAnnotatedClass(clazz); 53 | } else if (result.getL()) { 54 | praseClass(clazz); 55 | } else { 56 | //别的注解 57 | praseUnknowAnnotatedClass(clazz); 58 | } 59 | } 60 | } 61 | 62 | /** 63 | * pair的left指明是否是配置的bean,right指是否有@Bean注解 64 | */ 65 | private Pair checkBeanAnnotated(Class clazz) { 66 | if (clazz.isAnnotationPresent(Configuration.class) || clazz.isAnnotationPresent(Component.class)) { 67 | Method[] methods = clazz.getDeclaredMethods(); 68 | for (Method method : methods) { 69 | if (method.isAnnotationPresent(Bean.class)) { 70 | return Pair.of(true, true); 71 | } 72 | } 73 | return Pair.of(true, false); 74 | } 75 | return Pair.of(false, false); 76 | } 77 | 78 | private void praseBeanAnnotatedClass(Class clazz) throws Exception { 79 | BeanDefinition beanDefinition = handleTypeAnnot(clazz, true); 80 | if (beanDefinition == null) { 81 | return; 82 | } 83 | handleFieldAnnot(clazz, beanDefinition); 84 | //多一个步骤解析方法 85 | Map methodinfos = handleMethodAnnotAndRegister(clazz); 86 | ((BeanAnnotatedDefinition) beanDefinition).putmethodInfos(methodinfos); 87 | registerBean(beanDefinition); 88 | } 89 | 90 | private void praseClass(Class clazz) throws Exception { 91 | BeanDefinition beanDefinition = handleTypeAnnot(clazz, false); 92 | if (beanDefinition == null) { 93 | return; 94 | } 95 | handleFieldAnnot(clazz, beanDefinition); 96 | registerBean(beanDefinition); 97 | } 98 | 99 | private void praseUnknowAnnotatedClass(Class clazz) throws Exception { 100 | BeanDefinition beanDefinition = handleIntegrationAnnotation(clazz); 101 | if (beanDefinition == null) { 102 | return; 103 | } 104 | handleFieldAnnot(clazz, beanDefinition); 105 | registerBean(beanDefinition); 106 | } 107 | 108 | public abstract BeanDefinition handleIntegrationAnnotation(Class clazz) throws Exception; 109 | 110 | /** 111 | * TODO 重构,annotation去重,去掉多余的 @Component 112 | * 目前只有@Component一个注解是ElementType.ANNOTATION_TYPE的,且只有@Component和@Configuration可以注解类 113 | * 那么只针对当前model下定义的这些注解做特殊情况处理 114 | * 后续重构,支持任一的注解检查 115 | */ 116 | private Annotation[] deDuplicationAnnotation(Annotation[] annotations) { 117 | List componentIndex = new ArrayList<>(annotations.length); 118 | boolean flag = false; 119 | for (int i = 0; i < annotations.length; i++) { 120 | //有没有Component注解 121 | if (annotations[i].annotationType() == Component.class) { 122 | componentIndex.add(i); 123 | } else { 124 | //有没有被Component注解的注解 125 | if (isAnnotated(annotations[i].annotationType(), Component.class)) { 126 | flag = true; 127 | } 128 | } 129 | } 130 | if (flag && componentIndex.size() > 0) { 131 | //去掉多余的Component注解 132 | Annotation[] result = new Annotation[annotations.length - componentIndex.size()]; 133 | for (int i = 0, j = 0, index = 0; i < annotations.length; i++) { 134 | if (index < componentIndex.size()) { 135 | if (i == componentIndex.get(index)) { 136 | index++; 137 | } else { 138 | result[j] = annotations[i]; 139 | j++; 140 | } 141 | } else { 142 | result[j] = annotations[i]; 143 | j++; 144 | } 145 | 146 | } 147 | return result; 148 | } 149 | return annotations; 150 | } 151 | 152 | private boolean isAnnotated(Class front, Class after) { 153 | if (front.isAnnotationPresent(after)) { 154 | return true; 155 | } else { 156 | if (front.isAnnotation()) { 157 | Annotation[] annotations = front.getAnnotations(); 158 | for (Annotation annotation : annotations) { 159 | if (isAnnotated(annotation.annotationType(), after)) { 160 | return true; 161 | } 162 | } 163 | } 164 | } 165 | return false; 166 | } 167 | 168 | private BeanDefinition handleTypeAnnot(Class clazz, boolean isBeanAnnotated) throws Exception { 169 | Annotation[] annotations = clazz.getAnnotations(); 170 | annotations = deDuplicationAnnotation(annotations); 171 | for (Annotation annotation : annotations) { 172 | log.debug(annotation + " is component ? " + annotation.annotationType().isAnnotationPresent(Component.class)); 173 | if (annotation.annotationType() == Component.class) { 174 | //Component注解 175 | Component configAnnot = (Component) annotation; 176 | if (isBeanAnnotated) { 177 | return new BeanAnnotatedDefinition(getBeanName(configAnnot.name(), clazz), clazz); 178 | } else { 179 | return new BeanDefinition(getBeanName(configAnnot.name(), clazz), clazz); 180 | } 181 | } else if (annotation.annotationType().isAnnotationPresent(Component.class)) { 182 | //Configuration 183 | if (annotation.annotationType() == Configuration.class) { 184 | Configuration configAnnot = (Configuration) annotation; 185 | if (isBeanAnnotated) { 186 | return new BeanAnnotatedDefinition(getBeanName(configAnnot.name(), clazz), clazz); 187 | } else { 188 | return new BeanDefinition(getBeanName(configAnnot.name(), clazz), clazz); 189 | } 190 | } 191 | } 192 | } 193 | //有其他的注解,这些的解析交给子类完成 194 | return handleIntegrationAnnotation(clazz); 195 | } 196 | 197 | private void registerBean(BeanDefinition beanDefinition) throws Exception { 198 | log.debug("bean: {}", beanDefinition); 199 | if (getRegisterBeans().putIfAbsent(beanDefinition.getId(), beanDefinition) != null) { 200 | throw new BeanDefinitionException(String.format("bean is duplicate,bean name is '%s'", beanDefinition.getId())); 201 | } 202 | } 203 | 204 | private void handleFieldAnnot(Class clazz, BeanDefinition beanDefinition) throws Exception { 205 | Field[] fields = clazz.getDeclaredFields(); 206 | for (Field field : fields) { 207 | Annotation[] annotations = field.getAnnotations(); 208 | for (Annotation annotation : annotations) { 209 | if (annotation instanceof Value) { 210 | Value valueAnnot = (Value) annotation; 211 | //TODO 类型转化 212 | if (field.getType().equals(String.class)) { 213 | String configValue = valueAnnot.value(); 214 | beanDefinition.addProperty(new BeanPropertyValue(field.getName(), getConfigValue(PlaceholderPraser.prase(configValue)))); 215 | } else { 216 | throw new BeanDefinitionException( 217 | String.format("sorry, the field '%s', '@Value' only support String!!! , class: %s", 218 | field.getName(), clazz.getName())); 219 | } 220 | } else if (annotation instanceof Inject) { 221 | Inject injectAnnot = (Inject) annotation; 222 | BeanReference beanReference = new BeanReference(getBeanName(injectAnnot.name(), field.getType())); 223 | beanDefinition.addProperty(new BeanPropertyValue(field.getName(), beanReference)); 224 | } 225 | } 226 | } 227 | } 228 | 229 | private Map handleMethodAnnotAndRegister(Class clazz) throws BeanDefinitionException { 230 | Map methodInfos = new HashMap<>(); 231 | Method[] methods = clazz.getDeclaredMethods(); 232 | for (Method method : methods) { 233 | Annotation[] annotations = method.getAnnotations(); 234 | for (Annotation annotation : annotations) { 235 | if (annotation instanceof Bean) { 236 | if (method.getParameterCount() > 0) { 237 | throw new BeanDefinitionException(String.format("{} ,method annotated by '@Bean' is not support parameter, so let parameter blank", method)); 238 | } 239 | Bean beanAnnot = (Bean) annotation; 240 | String beanName = getBeanName(beanAnnot.name(), method.getName()); 241 | BeanDefinition beanDefinition = new BeanDefinition(beanName, method.getReturnType()); 242 | methodInfos.put(method.getName(), beanName); 243 | getRegisterBeans().putIfAbsent(beanDefinition.getId(), beanDefinition); 244 | } 245 | } 246 | } 247 | return methodInfos; 248 | } 249 | 250 | public void setScanPackages(List scanPackages) { 251 | this.scanPackages.addAll(scanPackages); 252 | } 253 | 254 | } 255 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/reader/AutoConfigBeanDefinitionReader.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.reader; 2 | 3 | import com.tg.tiny4j.commons.constants.ConfigurationElement; 4 | import com.tg.tiny4j.core.ioc.beans.BeanDefinition; 5 | import org.apache.commons.lang3.StringUtils; 6 | 7 | import java.util.Arrays; 8 | 9 | /** 10 | * Created by twogoods on 16/10/29. 11 | */ 12 | public class AutoConfigBeanDefinitionReader extends AnnotationBeanDefinitionReader { 13 | 14 | private void initConfig() throws Exception { 15 | //默认取application.properties 16 | loadConfig(ConfigurationElement.DEFAULT_CONFIG_FILE); 17 | //设置扫描的包 18 | String packages = getConfigValue(ConfigurationElement.COMPONENTSCAN); 19 | if (!StringUtils.isEmpty(packages)) { 20 | setScanPackages(Arrays.asList(packages.split(","))); 21 | } 22 | } 23 | 24 | @Override 25 | public void loadResource() throws Exception { 26 | initConfig(); 27 | super.loadResource(); 28 | } 29 | 30 | @Override 31 | public BeanDefinition handleIntegrationAnnotation(Class clazz) throws Exception { 32 | return null; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/reader/BeanDefinitionReader.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.reader; 2 | 3 | import com.tg.tiny4j.core.ioc.beans.BeanDefinition; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * Created by twogoods on 16/10/26. 9 | */ 10 | public interface BeanDefinitionReader { 11 | 12 | void loadResource() throws Exception; 13 | 14 | Map getRegisterBeans(); 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/reader/ClassScanner.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.reader; 2 | 3 | import org.apache.commons.io.IOUtils; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.io.File; 9 | import java.io.FileNotFoundException; 10 | import java.io.IOException; 11 | import java.net.JarURLConnection; 12 | import java.net.URL; 13 | import java.net.URLConnection; 14 | import java.util.Enumeration; 15 | import java.util.HashSet; 16 | import java.util.List; 17 | import java.util.Set; 18 | import java.util.jar.JarEntry; 19 | import java.util.jar.JarFile; 20 | import java.util.jar.JarInputStream; 21 | 22 | /** 23 | * Created by twogoods on 16/10/28. 24 | */ 25 | public class ClassScanner { 26 | private static final Logger log = LoggerFactory.getLogger(ClassScanner.class); 27 | public static Set getClasses(List packages) throws Exception { 28 | Set classes = new HashSet(); 29 | for (String packageName : packages) { 30 | if (StringUtils.isEmpty(packageName)) { 31 | continue; 32 | } 33 | getClassByPackage(packageName.replace(".", File.separator), classes); 34 | } 35 | return classes; 36 | } 37 | 38 | private static void getClassByPackage(String packageName, Set classes) throws Exception { 39 | Enumeration baseURLs = ClassScanner.class.getClassLoader().getResources(packageName); 40 | URL baseURL = null; 41 | while (baseURLs.hasMoreElements()) { 42 | baseURL = baseURLs.nextElement(); 43 | if (baseURL != null) { 44 | log.debug("componentscan find: {}",baseURL.toString()); 45 | String protocol = baseURL.getProtocol(); 46 | String basePath = baseURL.getFile(); 47 | if ("jar".equals(protocol)) { 48 | //实际运行中看到了这样的形式的jar目录 /BOOT-INF/classes!/com ,classes是一个目录,去掉后面的!,原因还没弄明白. 49 | basePath = basePath.replace("classes!", "classes"); 50 | String[] paths = basePath.split("jar!/"); 51 | if (paths.length == 2) { 52 | findFileInJar(paths[0] + "jar!/", paths[1], classes); 53 | } else if (paths.length > 2) { 54 | int index = basePath.lastIndexOf("jar!/") + "jar".length(); 55 | String lastJarPath = basePath.substring(0, index); 56 | String packagepath = basePath.substring(index + "!/".length(), basePath.length()); 57 | findFileInJarWithinJar(lastJarPath, packagepath, classes); 58 | } 59 | } else { 60 | getClassesInFile(basePath, packageName, classes); 61 | } 62 | } 63 | } 64 | } 65 | 66 | private static void findFileInJar(String filePath, String packagePath, Set classes) throws IOException { 67 | URL url = new URL("jar", null, 0, filePath); 68 | URLConnection con = url.openConnection(); 69 | if (con instanceof JarURLConnection) { 70 | JarURLConnection result = (JarURLConnection) con; 71 | JarFile jarFile = result.getJarFile(); 72 | for (final Enumeration enumJar = jarFile.entries(); enumJar.hasMoreElements(); ) { 73 | JarEntry entry = enumJar.nextElement(); 74 | filterClass(entry.getName(), packagePath, classes); 75 | } 76 | jarFile.close(); 77 | } 78 | } 79 | 80 | private static void findFileInJarWithinJar(String filePath, String packagePath, Set classes) throws IOException { 81 | URL url = new URL("jar", null, 0, filePath); 82 | URLConnection con = url.openConnection(); 83 | if (con instanceof JarURLConnection) { 84 | JarURLConnection jarURLConnection = (JarURLConnection) con; 85 | JarInputStream jarInputStream = new JarInputStream(jarURLConnection.getInputStream()); 86 | JarEntry entry; 87 | while ((entry = jarInputStream.getNextJarEntry()) != null) { 88 | filterClass(entry.getName(), packagePath, classes); 89 | } 90 | IOUtils.closeQuietly(jarInputStream); 91 | } 92 | } 93 | 94 | private static void filterClass(String filePath, String packageName, Set classes) { 95 | if (filePath.startsWith(packageName) && filePath.endsWith(".class")) { 96 | classes.add(getWholeClassName(filePath)); 97 | } 98 | } 99 | 100 | 101 | public static void getClassesInFile(String filePath, String packagePath, Set classes) throws Exception { 102 | File file = new File(filePath); 103 | if (!file.exists()) { 104 | throw new FileNotFoundException("check component-scan config, file or directory not found, path is " + filePath); 105 | } 106 | for (String fileName : file.list()) { 107 | String childFilePath = filePath; 108 | if (filePath.endsWith("/")) { 109 | childFilePath = childFilePath + fileName; 110 | } else { 111 | childFilePath = childFilePath + File.separator + fileName; 112 | } 113 | if (new File(childFilePath).isDirectory()) { 114 | getClassesInFile(childFilePath, packagePath, classes); 115 | } else if (fileName.endsWith(".class")) { 116 | String className = getWholeClassName(childFilePath); 117 | classes.add(className); 118 | } 119 | } 120 | } 121 | 122 | private static String getWholeClassName(String filePath) { 123 | if (filePath.indexOf("classes/") != -1) { 124 | return filePath.substring(filePath.indexOf("classes/") + "classes/".length(), 125 | filePath.indexOf(".class")).replaceAll("/", "."); 126 | } 127 | return filePath.substring(0, filePath.indexOf(".class")).replaceAll("/", "."); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/reader/PackageChecker.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.reader; 2 | 3 | import java.util.Collections; 4 | import java.util.Comparator; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | 8 | /** 9 | * Created by twogoods on 16/10/29. 10 | */ 11 | public class PackageChecker { 12 | /** 13 | * 多个包名去除有包涵关系的包 14 | * 15 | * @param arr 16 | * @return 17 | */ 18 | protected static List deDuplicatePackage(String[] arr) { 19 | List list = new LinkedList<>(); 20 | for (String item : arr) { 21 | list.add(item); 22 | } 23 | //从短到长排序 24 | Collections.sort(list, new Comparator() { 25 | @Override 26 | public int compare(String o1, String o2) { 27 | return o1.length() > o2.length() ? 0 : 1; 28 | } 29 | }); 30 | for (int i = 0; i < list.size(); i++) { 31 | for (int j = list.size() - 1; i < j; j--) { 32 | if (list.get(j).contains(list.get(i))) { 33 | list.remove(j); 34 | } 35 | } 36 | } 37 | return list; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/reader/PlaceholderPraser.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.reader; 2 | 3 | 4 | /** 5 | * Created by twogoods on 16/10/29. 6 | */ 7 | public class PlaceholderPraser { 8 | 9 | public static KeyAndDefault prase(String config) { 10 | if (config.startsWith("${") && config.endsWith("}")) { 11 | String subConfig = config.substring(2, config.length() - 1); 12 | String[] configAndDefault = subConfig.split(":"); 13 | if (configAndDefault.length == 1) { 14 | return new KeyAndDefault(configAndDefault[0], null); 15 | } else { 16 | return new KeyAndDefault(configAndDefault[0], configAndDefault[1]); 17 | } 18 | } 19 | return new KeyAndDefault(config, null); 20 | } 21 | 22 | public static class KeyAndDefault { 23 | private String name; 24 | private String defaultValue; 25 | 26 | private KeyAndDefault(String name, String defaultValue) { 27 | this.name = name; 28 | this.defaultValue = defaultValue; 29 | } 30 | 31 | public String getName() { 32 | return name; 33 | } 34 | 35 | public String getDefaultValue() { 36 | return defaultValue; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/beans/reader/XmlBeanDefinitionReader.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.reader; 2 | 3 | import com.tg.tiny4j.commons.utils.Validate; 4 | import com.tg.tiny4j.core.ioc.beans.BeanDefinition; 5 | import com.tg.tiny4j.core.ioc.beans.BeanPropertyValue; 6 | import com.tg.tiny4j.core.ioc.beans.BeanReference; 7 | import com.tg.tiny4j.core.ioc.exception.BeanDefinitionException; 8 | import com.tg.tiny4j.core.ioc.resource.ResourceLoad; 9 | import org.apache.commons.lang3.StringUtils; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.w3c.dom.Document; 13 | import org.w3c.dom.Element; 14 | import org.w3c.dom.Node; 15 | import org.w3c.dom.NodeList; 16 | 17 | import javax.xml.parsers.DocumentBuilder; 18 | import javax.xml.parsers.DocumentBuilderFactory; 19 | import java.io.InputStream; 20 | import java.util.List; 21 | 22 | /** 23 | * Created by twogoods on 16/10/25. 24 | */ 25 | public class XmlBeanDefinitionReader extends AnnotationBeanDefinitionReader { 26 | private static Logger log = LoggerFactory.getLogger(XmlBeanDefinitionReader.class); 27 | 28 | private String location; 29 | 30 | public XmlBeanDefinitionReader(String location) { 31 | this.location = location; 32 | } 33 | 34 | @Override 35 | public void loadResource() throws Exception { 36 | log.debug("XmlBeanDefinitionReader load..."); 37 | InputStream inputStream = ResourceLoad.getInstance().loadResource(location).getInputStream(); 38 | try { 39 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 40 | DocumentBuilder docBuilder = factory.newDocumentBuilder(); 41 | Document doc = docBuilder.parse(inputStream); 42 | Element root = doc.getDocumentElement(); 43 | initConfig(root); 44 | //解析xml里配置的bean 45 | praseBeanDefinitions(root); 46 | //开始扫描注解的bean 47 | super.loadResource(); 48 | } finally { 49 | inputStream.close(); 50 | } 51 | } 52 | 53 | @Override 54 | public BeanDefinition handleIntegrationAnnotation(Class clazz) throws Exception { 55 | return null; 56 | } 57 | 58 | /** 59 | * config默认在classpath下取 60 | * 61 | * @param root 62 | */ 63 | private void initConfig(Element root) throws Exception { 64 | NodeList propertieslist = root.getElementsByTagName("configs"); 65 | if (propertieslist.getLength() != 1) { 66 | throw new BeanDefinitionException("In XML, should be unique."); 67 | } 68 | if (!(propertieslist.item(0) instanceof Element)) { 69 | return; 70 | } 71 | Element configRoot = (Element) propertieslist.item(0); 72 | //配置文件 73 | NodeList propertyFiles = configRoot.getElementsByTagName("property-file"); 74 | if (propertyFiles.getLength() > 0) { 75 | String filesPath = propertyFiles.item(0).getTextContent(); 76 | if (StringUtils.isEmpty(filesPath)) { 77 | return; 78 | } 79 | String[] pathArr = filesPath.split(","); 80 | for (String filePath : pathArr) { 81 | loadConfig(filePath); 82 | } 83 | } else { 84 | //默认取application.properties 85 | loadConfig("application.properties"); 86 | } 87 | //设置扫描的包 88 | NodeList packageFiles = configRoot.getElementsByTagName("component-scan"); 89 | if (packageFiles.getLength() > 0) { 90 | String packageNames = packageFiles.item(0).getTextContent(); 91 | packageNames = getConfigValue(PlaceholderPraser.prase(packageNames)); 92 | if (StringUtils.isEmpty(packageNames)) { 93 | return; 94 | } 95 | String[] packageArr = packageNames.split(","); 96 | List packages = PackageChecker.deDuplicatePackage(packageArr); 97 | setScanPackages(packages); 98 | } 99 | } 100 | 101 | private void praseBeanDefinitions(Element root) throws Exception { 102 | NodeList list = root.getElementsByTagName("bean"); 103 | for (int i = 0; i < list.getLength(); i++) { 104 | Node node = list.item(i); 105 | if (node instanceof Element) { 106 | Element ele = (Element) node; 107 | readBean(ele); 108 | } 109 | } 110 | } 111 | 112 | private void readBean(Element ele) throws Exception { 113 | String className = ele.getAttribute("class"); 114 | if (Validate.isEmpty(className)) { 115 | throw new BeanDefinitionException("Bean definition need 'class' property"); 116 | } 117 | String id = ele.getAttribute("id"); 118 | if (Validate.isEmpty(id)) { 119 | id = getBeanNameByClassName(className); 120 | } 121 | BeanDefinition beanDefinition = new BeanDefinition(id, className); 122 | processProperty(ele, beanDefinition); 123 | if (getRegisterBeans().putIfAbsent(id, beanDefinition) != null) { 124 | throw new BeanDefinitionException(String.format("bean is duplicate,bean name is '%s'", id)); 125 | } 126 | } 127 | 128 | 129 | private void processProperty(Element ele, BeanDefinition beanDefinition) throws Exception { 130 | NodeList propertyNode = ele.getElementsByTagName("property"); 131 | for (int i = 0; i < propertyNode.getLength(); i++) { 132 | Node node = propertyNode.item(i); 133 | if (node instanceof Element) { 134 | Element propertyEle = (Element) node; 135 | String name = propertyEle.getAttribute("name"); 136 | if (Validate.isEmpty(name)) { 137 | throw new BeanDefinitionException("Bean definition need 'name' property"); 138 | } 139 | String value = propertyEle.getAttribute("value"); 140 | String ref = propertyEle.getAttribute("ref"); 141 | if (!Validate.isEmpty(value)) { 142 | beanDefinition.addProperty(new BeanPropertyValue(name, value)); 143 | } else if (!Validate.isEmpty(ref)) { 144 | BeanReference beanReference = new BeanReference(ref); 145 | beanDefinition.addProperty(new BeanPropertyValue(name, beanReference)); 146 | } else { 147 | throw new BeanDefinitionException("Bean definition need 'name' property"); 148 | } 149 | } 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/context/AbstractApplicationContext.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.context; 2 | 3 | import com.tg.tiny4j.core.ioc.beans.BeanDefinition; 4 | import com.tg.tiny4j.core.ioc.beans.factory.AbstractBeanFactory; 5 | 6 | /** 7 | * Created by twogoods on 16/10/25. 8 | */ 9 | public abstract class AbstractApplicationContext implements ApplicationContext{ 10 | protected AbstractBeanFactory beanFactory; 11 | 12 | protected void refresh() throws Exception { 13 | registerBeans(); 14 | //初始化容器上下文类 15 | instanceContextHolder(); 16 | //预先初始化所有的bean 17 | instanceBeanFactory(); 18 | } 19 | 20 | protected void registerBeans() throws Exception {} 21 | 22 | /** 23 | *增加一个名为applicationContextHolder的bean保存容器上下文 24 | */ 25 | private void instanceContextHolder(){ 26 | BeanDefinition beanDefinition=new BeanDefinition("applicationContextHolder",ApplicationContextHolder.class); 27 | beanDefinition.setBean(new ApplicationContextHolder(this)); 28 | beanFactory.addBeanDefinition("applicationContextHolder",beanDefinition); 29 | } 30 | 31 | public void instanceBeanFactory() throws Exception { 32 | beanFactory.preInstantiateSingletons(); 33 | } 34 | 35 | @Override 36 | public Object getBean(String name) throws Exception { 37 | return beanFactory.getBean(name); 38 | } 39 | 40 | @Override 41 | public T getBean(String name, Class clazz) throws Exception { 42 | return beanFactory.getBean(name,clazz); 43 | } 44 | @Override 45 | public boolean containsBean(String name) throws Exception { 46 | return beanFactory.containsBean(name); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/context/ApplicationContext.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.context; 2 | 3 | import com.tg.tiny4j.core.ioc.beans.factory.BeanFactory; 4 | 5 | /** 6 | * Created by twogoods on 16/10/25. 7 | */ 8 | public interface ApplicationContext extends BeanFactory { 9 | } 10 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/context/ApplicationContextHolder.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.context; 2 | 3 | /** 4 | * Created by twogoods on 16/10/25. 5 | */ 6 | public class ApplicationContextHolder { 7 | private ApplicationContext applicationContext; 8 | 9 | public ApplicationContextHolder(ApplicationContext applicationContext) { 10 | this.applicationContext = applicationContext; 11 | } 12 | Object getBean(String name) throws Exception{ 13 | return applicationContext.getBean(name); 14 | } 15 | 16 | T getBean(String name, Class clazz) throws Exception{ 17 | return applicationContext.getBean(name,clazz); 18 | } 19 | 20 | boolean containsBean(String name) throws Exception{ 21 | return applicationContext.containsBean(name); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/context/ClassPathXmlApplicationContext.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.context; 2 | 3 | import com.tg.tiny4j.core.ioc.beans.factory.DefaultBeanFactory; 4 | import com.tg.tiny4j.core.ioc.beans.reader.BeanDefinitionReader; 5 | import com.tg.tiny4j.core.ioc.beans.reader.XmlBeanDefinitionReader; 6 | 7 | /** 8 | * Created by twogoods on 16/10/25. 9 | */ 10 | public class ClassPathXmlApplicationContext extends AbstractApplicationContext{ 11 | private String configLocation; 12 | 13 | public ClassPathXmlApplicationContext(String configLocation) throws Exception { 14 | this.configLocation = configLocation; 15 | refresh(); 16 | } 17 | 18 | protected void registerBeans() throws Exception { 19 | BeanDefinitionReader beanDefinitionReader=new XmlBeanDefinitionReader(configLocation); 20 | beanDefinitionReader.loadResource(); 21 | beanFactory=new DefaultBeanFactory(); 22 | beanFactory.addBeanDefinition(beanDefinitionReader.getRegisterBeans()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/exception/BeanDefinitionException.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.exception; 2 | 3 | /** 4 | * Created by twogoods on 16/10/26. 5 | */ 6 | public class BeanDefinitionException extends Exception{ 7 | public BeanDefinitionException(String message) { 8 | super(message); 9 | } 10 | 11 | public BeanDefinitionException(String message, Throwable cause) { 12 | super(message, cause); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/exception/BeanException.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.exception; 2 | 3 | /** 4 | * Created by twogoods on 16/10/26. 5 | */ 6 | public class BeanException extends Exception{ 7 | public BeanException(String message) { 8 | super(message); 9 | } 10 | 11 | public BeanException(String message, Throwable cause) { 12 | super(message, cause); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/exception/ConfigurationException.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.exception; 2 | 3 | /** 4 | * Created by twogoods on 16/10/29. 5 | */ 6 | public class ConfigurationException extends Exception{ 7 | public ConfigurationException(String message) { 8 | super(message); 9 | } 10 | 11 | public ConfigurationException(String message, Throwable cause) { 12 | super(message, cause); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/exception/PropertyDuplicateException.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.exception; 2 | 3 | /** 4 | * Created by twogoods on 16/10/26. 5 | */ 6 | public class PropertyDuplicateException extends Exception { 7 | public PropertyDuplicateException(String message) { 8 | super(message); 9 | } 10 | 11 | public PropertyDuplicateException(String message, Throwable cause) { 12 | super(message, cause); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/resource/Resource.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.resource; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | 6 | /** 7 | * Created by twogoods on 16/10/25. 8 | */ 9 | public interface Resource { 10 | 11 | InputStream getInputStream() throws IOException; 12 | } 13 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/resource/ResourceLoad.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.resource; 2 | 3 | import com.tg.tiny4j.core.ioc.exception.ConfigurationException; 4 | 5 | import java.io.InputStream; 6 | import java.net.URL; 7 | import java.util.Properties; 8 | 9 | /** 10 | * Created by twogoods on 16/10/25. 11 | */ 12 | public class ResourceLoad { 13 | 14 | private static ResourceLoad resourceLoad = new ResourceLoad(); 15 | 16 | public static ResourceLoad getInstance() { 17 | return resourceLoad; 18 | } 19 | 20 | private ResourceLoad() { 21 | } 22 | 23 | public Resource loadResource(String location) { 24 | URL url = getClass().getClassLoader().getResource(location); 25 | return new UrlResource(url); 26 | } 27 | 28 | public Properties loadConfig(String path) throws Exception { 29 | InputStream in = getClass().getClassLoader().getResourceAsStream(path); 30 | if(in==null){ 31 | throw new ConfigurationException(String.format("'%s' is not exist",path)); 32 | } 33 | try { 34 | Properties prop = new Properties(); 35 | prop.load(in); 36 | return prop; 37 | } finally { 38 | in.close(); 39 | } 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/ioc/resource/UrlResource.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.resource; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.net.URL; 6 | import java.net.URLConnection; 7 | 8 | /** 9 | * Created by twogoods on 16/10/25. 10 | */ 11 | public class UrlResource implements Resource { 12 | private URL url; 13 | 14 | public UrlResource(URL url) { 15 | this.url = url; 16 | } 17 | 18 | @Override 19 | public InputStream getInputStream() throws IOException { 20 | URLConnection con=url.openConnection(); 21 | return con.getInputStream(); 22 | } 23 | 24 | public URL getUrl() { 25 | return url; 26 | } 27 | 28 | public void setUrl(URL url) { 29 | this.url = url; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/web/integration/BootAppBeanDefinitionReader.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.web.integration; 2 | 3 | import com.tg.tiny4j.core.ioc.beans.BeanDefinition; 4 | import com.tg.tiny4j.core.ioc.beans.reader.AutoConfigBeanDefinitionReader; 5 | 6 | /** 7 | * Description: 8 | * 9 | * @author twogoods 10 | * @version 0.1 11 | * @since 2017-03-31 12 | */ 13 | public class BootAppBeanDefinitionReader extends AutoConfigBeanDefinitionReader{ 14 | private HandleAnnotation handle; 15 | 16 | public BootAppBeanDefinitionReader(HandleAnnotation handle) { 17 | this.handle = handle; 18 | } 19 | 20 | @Override 21 | public BeanDefinition handleIntegrationAnnotation(Class clazz) throws Exception { 22 | return handle.handle(clazz); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/web/integration/ContextListener/AbstractBootContextListener.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.web.integration.ContextListener; 2 | 3 | import com.tg.tiny4j.commons.constants.WebApplicationEnvironment; 4 | import com.tg.tiny4j.core.web.integration.HandleRegistry; 5 | import com.tg.tiny4j.core.web.integration.context.BootApplicationContext; 6 | import com.tg.tiny4j.core.web.integration.context.WebApplicationContext; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import javax.servlet.ServletContextEvent; 11 | import javax.servlet.ServletContextListener; 12 | 13 | /** 14 | * Description: 15 | * 16 | * @author twogoods 17 | * @version 0.1 18 | * @since 2017-03-31 19 | */ 20 | public abstract class AbstractBootContextListener implements ServletContextListener { 21 | private static Logger log = LoggerFactory.getLogger(AbstractBootContextListener.class); 22 | 23 | private WebApplicationContext webApplicationContext; 24 | private HandleRegistry registry = new HandleRegistry(); 25 | 26 | public abstract void registerHandle(HandleRegistry registry); 27 | 28 | public abstract void requestMapInitialized(ServletContextEvent servletContextEvent, WebApplicationContext applicationContext) throws Exception; 29 | 30 | @Override 31 | public void contextInitialized(ServletContextEvent servletContextEvent) { 32 | try { 33 | registerHandle(registry); 34 | webApplicationContext = new BootApplicationContext(registry.getHandle()); 35 | requestMapInitialized(servletContextEvent, webApplicationContext); 36 | servletContextEvent.getServletContext().setAttribute(WebApplicationEnvironment.RUN_MODE, WebApplicationEnvironment.CONTAINER_MODE); 37 | // servletContextEvent.getServletContext().setAttribute("root_applicationcontext", webApplicationContext); 38 | } catch (Exception e) { 39 | log.error("Context initialization failed", e); 40 | } 41 | } 42 | 43 | @Override 44 | public void contextDestroyed(ServletContextEvent servletContextEvent) { 45 | log.info("SingleRestLoaderListener destroyed..."); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/web/integration/ContextListener/AbstractWebContextListener.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.web.integration.ContextListener; 2 | 3 | import com.tg.tiny4j.commons.constants.WebApplicationEnvironment; 4 | import com.tg.tiny4j.core.web.integration.HandleRegistry; 5 | import com.tg.tiny4j.core.web.integration.context.ServletContainerApplicationContext; 6 | import com.tg.tiny4j.core.web.integration.context.WebApplicationContext; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import javax.servlet.ServletContextEvent; 11 | import javax.servlet.ServletContextListener; 12 | 13 | /** 14 | * Created by twogoods on 16/11/5. 15 | */ 16 | public abstract class AbstractWebContextListener implements ServletContextListener { 17 | 18 | private static Logger log = LoggerFactory.getLogger(AbstractWebContextListener.class); 19 | 20 | private WebApplicationContext webApplicationContext; 21 | private HandleRegistry registry = new HandleRegistry(); 22 | 23 | public abstract void registerHandle(HandleRegistry registry); 24 | 25 | public abstract void requestMapInitialized(ServletContextEvent servletContextEvent, WebApplicationContext applicationContext) throws Exception; 26 | 27 | @Override 28 | public void contextInitialized(ServletContextEvent servletContextEvent) { 29 | try { 30 | registerHandle(registry); 31 | webApplicationContext = new ServletContainerApplicationContext(registry.getHandle()); 32 | requestMapInitialized(servletContextEvent, webApplicationContext); 33 | servletContextEvent.getServletContext().setAttribute(WebApplicationEnvironment.RUN_MODE, WebApplicationEnvironment.CONTAINER_MODE); 34 | // servletContextEvent.getServletContext().setAttribute("root_applicationcontext", webApplicationContext); 35 | } catch (Exception e) { 36 | log.error("Context initialization failed", e); 37 | } 38 | } 39 | 40 | @Override 41 | public void contextDestroyed(ServletContextEvent servletContextEvent) { 42 | log.info("SingleRestLoaderListener destroyed..."); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/web/integration/HandleAnnotation.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.web.integration; 2 | 3 | import com.tg.tiny4j.core.ioc.beans.BeanDefinition; 4 | 5 | /** 6 | * Created by twogoods on 16/11/5. 7 | */ 8 | public interface HandleAnnotation { 9 | BeanDefinition handle(Class clazz) throws Exception; 10 | } 11 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/web/integration/HandleRegistry.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.web.integration; 2 | 3 | /** 4 | * Created by twogoods on 16/11/5. 5 | */ 6 | public class HandleRegistry { 7 | private HandleAnnotation handle; 8 | 9 | public void addHandle(HandleAnnotation handle){ 10 | this.handle=handle; 11 | } 12 | 13 | public HandleAnnotation getHandle() { 14 | return handle; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/web/integration/WebAppBeanDefinitionReader.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.web.integration; 2 | 3 | import com.tg.tiny4j.core.ioc.beans.BeanDefinition; 4 | import com.tg.tiny4j.core.ioc.beans.reader.XmlBeanDefinitionReader; 5 | 6 | 7 | /** 8 | * Created by twogoods on 16/11/1. 9 | */ 10 | public class WebAppBeanDefinitionReader extends XmlBeanDefinitionReader { 11 | 12 | private HandleAnnotation handle; 13 | 14 | public WebAppBeanDefinitionReader(String location, HandleAnnotation handle) { 15 | super(location); 16 | this.handle = handle; 17 | } 18 | 19 | public WebAppBeanDefinitionReader(HandleAnnotation handle) { 20 | this("application.xml", handle); 21 | } 22 | 23 | @Override 24 | public BeanDefinition handleIntegrationAnnotation(Class clazz) throws Exception { 25 | return handle.handle(clazz); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/web/integration/context/BootApplicationContext.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.web.integration.context; 2 | 3 | import com.tg.tiny4j.core.ioc.beans.factory.DefaultBeanFactory; 4 | import com.tg.tiny4j.core.web.integration.BootAppBeanDefinitionReader; 5 | import com.tg.tiny4j.core.web.integration.HandleAnnotation; 6 | /** 7 | * Description: 8 | * 9 | * @author twogoods 10 | * @version 0.1 11 | * @since 2017-03-31 12 | */ 13 | public class BootApplicationContext extends WebApplicationContext { 14 | private HandleAnnotation handle; 15 | 16 | public BootApplicationContext(HandleAnnotation handle) throws Exception { 17 | super(); 18 | this.handle = handle; 19 | refresh(); 20 | } 21 | 22 | protected void registerBeans() throws Exception { 23 | BootAppBeanDefinitionReader bootAppBeanDefinitionReader = new BootAppBeanDefinitionReader(handle); 24 | //读取bean信息 25 | bootAppBeanDefinitionReader.loadResource(); 26 | beanFactory = new DefaultBeanFactory(); 27 | beanFactory.addBeanDefinition(bootAppBeanDefinitionReader.getRegisterBeans()); 28 | } 29 | } -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/web/integration/context/ServletContainerApplicationContext.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.web.integration.context; 2 | 3 | import com.tg.tiny4j.core.ioc.beans.factory.DefaultBeanFactory; 4 | import com.tg.tiny4j.core.web.integration.HandleAnnotation; 5 | import com.tg.tiny4j.core.web.integration.WebAppBeanDefinitionReader; 6 | 7 | /** 8 | * Description: 9 | * 10 | * @author twogoods 11 | * @version 0.1 12 | * @since 2017-03-31 13 | */ 14 | public class ServletContainerApplicationContext extends WebApplicationContext { 15 | private HandleAnnotation handle; 16 | 17 | public ServletContainerApplicationContext(HandleAnnotation handle) throws Exception { 18 | super(); 19 | this.handle = handle; 20 | refresh(); 21 | } 22 | 23 | protected void registerBeans() throws Exception { 24 | WebAppBeanDefinitionReader webAppBeanDefinitionReader = new WebAppBeanDefinitionReader(handle); 25 | //读取bean信息 26 | webAppBeanDefinitionReader.loadResource(); 27 | beanFactory = new DefaultBeanFactory(); 28 | beanFactory.addBeanDefinition(webAppBeanDefinitionReader.getRegisterBeans()); 29 | } 30 | } -------------------------------------------------------------------------------- /core/src/main/java/com/tg/tiny4j/core/web/integration/context/WebApplicationContext.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.web.integration.context; 2 | 3 | import com.tg.tiny4j.core.ioc.context.AbstractApplicationContext; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * Created by twogoods on 16/11/2. 10 | */ 11 | public abstract class WebApplicationContext extends AbstractApplicationContext { 12 | public Map getBeans(List names) throws Exception { 13 | Map beans = new HashMap<>(); 14 | for (String name : names) { 15 | beans.put(name, getBean(name)); 16 | } 17 | return beans; 18 | } 19 | } -------------------------------------------------------------------------------- /core/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | dataSource.driverClass=com.mysql.jdbc.Driver 2 | dataSource.url=jdbc:mysql://127.0.0.1:3306/test 3 | dataSource.monUser=root 4 | dataSource.password= 5 | dataSource.maxPoolSize=11 6 | dataSource.minPoolSize=5 7 | dataSource.maxStatements=8 -------------------------------------------------------------------------------- /core/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /core/src/test/java/com/tg/tiny4j/core/aop/Add.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop; 2 | 3 | /** 4 | * Created by twogoods on 16/10/24. 5 | */ 6 | public class Add{ 7 | 8 | private String prop; 9 | 10 | public int add(int a, int b) { 11 | System.out.println("prop:"+prop); 12 | return a+b; 13 | } 14 | 15 | public int add(int a) { 16 | return a+a; 17 | } 18 | 19 | 20 | public String getProp() { 21 | return prop; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /core/src/test/java/com/tg/tiny4j/core/aop/AddOperate.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop; 2 | 3 | /** 4 | * Created by twogoods on 16/10/30. 5 | */ 6 | public class AddOperate implements Operate{ 7 | private String prop; 8 | @Override 9 | public int cal(int a, int b) { 10 | System.out.println("method: cal(a,b)"); 11 | //System.out.println("prop:"+prop); 12 | return a+b+cal(a); 13 | } 14 | 15 | @Override 16 | public int cal(int a) { 17 | System.out.println("method: cal(a)"); 18 | return a+a; 19 | } 20 | 21 | @Override 22 | public int calno() { 23 | return 0; 24 | } 25 | 26 | 27 | public String getProp() { 28 | return prop; 29 | } 30 | 31 | public void setProp(String prop) { 32 | this.prop = prop; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /core/src/test/java/com/tg/tiny4j/core/aop/CglibDynamicAopProxyTest.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop; 2 | 3 | import com.tg.tiny4j.core.aop.advice.AopAdvice; 4 | import com.tg.tiny4j.core.aop.advice.Target; 5 | import com.tg.tiny4j.core.aop.exception.AdviceDefinitionException; 6 | import net.sf.cglib.proxy.Enhancer; 7 | import net.sf.cglib.proxy.MethodInterceptor; 8 | import net.sf.cglib.proxy.MethodProxy; 9 | import org.junit.Test; 10 | 11 | import java.io.File; 12 | import java.lang.reflect.Field; 13 | import java.lang.reflect.InvocationTargetException; 14 | import java.lang.reflect.Method; 15 | import java.util.Arrays; 16 | 17 | /** 18 | * Created by twogoods on 16/10/24. 19 | */ 20 | public class CglibDynamicAopProxyTest { 21 | @Test 22 | public void test() throws Exception { 23 | AopAdvice aopAdvice = new AopAdvice(); 24 | aopAdvice.setTarget(new Target(Add.class)); 25 | aopAdvice.setInterceptor(new TestAopInterceptor()); 26 | CglibAopProxy cglibDynamicAopProxy = new CglibAopProxy(aopAdvice); 27 | Add operate = (Add) cglibDynamicAopProxy.getProxy(); 28 | System.out.println(operate.add(1, 2)); 29 | } 30 | 31 | 32 | 33 | @Test 34 | public void originTest() throws Exception { 35 | Enhancer enhancer = new Enhancer(); 36 | enhancer.setSuperclass(Add.class); 37 | enhancer.setCallback(new MethodInterceptor() { 38 | @Override 39 | public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) 40 | throws Throwable { 41 | if (method.getDeclaringClass() != Object.class && method.getReturnType() == String.class) { 42 | return "Hello cglib!"; 43 | } else { 44 | return proxy.invokeSuper(obj, args); 45 | } 46 | } 47 | }); 48 | Add proxy = (Add) enhancer.create(); 49 | System.out.println(proxy.getProp()); 50 | System.out.println(proxy.getClass().getSuperclass()); 51 | } 52 | 53 | @Test 54 | public void anotherTest() throws Exception { 55 | AopAdvice aopAdvice = new AopAdvice(); 56 | aopAdvice.setTarget(new Target(Add.class)); 57 | aopAdvice.setInterceptor(new TestAopInterceptor()); 58 | CglibAopProxy cglibDynamicAopProxy = new CglibAopProxy(aopAdvice); 59 | Add operate = (Add) cglibDynamicAopProxy.getProxy(); 60 | System.out.println("--------------field-------------"); 61 | Field[] fields = operate.getClass().getFields(); 62 | for (Field f : fields) { 63 | System.out.println(f); 64 | } 65 | //上面无法得到属性的field,利用这种方式给代理对象赋值 66 | Field f=Add.class.getDeclaredField("prop"); 67 | f.setAccessible(true); 68 | f.set(operate,"twogoods"); 69 | System.out.println(operate.getProp()); 70 | } 71 | 72 | @Test 73 | public void autoSetTest() throws Exception { 74 | AopAdvice aopAdvice = new AopAdvice(); 75 | aopAdvice.setTarget(new Target(Add.class)); 76 | //TestAopInterceptor拦截了set方法,实现本质上与上一个测试类是一样的 77 | aopAdvice.setInterceptor(new TestAopInterceptor()); 78 | AutoSetterCglibAopProxy cglibDynamicAopProxy = new AutoSetterCglibAopProxy(aopAdvice); 79 | Add operate = (Add) cglibDynamicAopProxy.getProxy(); 80 | 81 | System.out.println(operate.add(1, 2)); 82 | 83 | System.out.println("*******"); 84 | Method setM = operate.getClass().getMethod("setProp", String.class); 85 | System.out.println(setM); 86 | setM.invoke(operate, "twogoods"); 87 | System.out.println(operate.getProp()); 88 | } 89 | } -------------------------------------------------------------------------------- /core/src/test/java/com/tg/tiny4j/core/aop/JdkDynamicAopProxyTest.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop; 2 | 3 | import com.tg.tiny4j.core.aop.advice.AopAdvice; 4 | import com.tg.tiny4j.core.aop.advice.Target; 5 | import com.tg.tiny4j.core.aop.exception.AdviceDefinitionException; 6 | import org.junit.Test; 7 | 8 | import java.lang.reflect.Method; 9 | 10 | /** 11 | * Created by twogoods on 16/10/24. 12 | */ 13 | public class JdkDynamicAopProxyTest { 14 | 15 | @Test 16 | public void test() throws Exception { 17 | AddOperate add=new AddOperate(); 18 | add.setProp("jdk..."); 19 | AopAdvice aopAdvice=new AopAdvice(); 20 | aopAdvice.setTarget(new Target(add,AddOperate.class,AddOperate.class.getInterfaces())); 21 | aopAdvice.setInterceptor(new TestAopInterceptor()); 22 | JdkDynamicAopProxy jdkDynamicAopProxy=new JdkDynamicAopProxy(aopAdvice); 23 | Operate addproxy=(Operate)jdkDynamicAopProxy.getProxy(); 24 | //int result=addproxy.cal(2, 4); 25 | 26 | // Method m=addproxy.getClass().getDeclaredMethod("cal",int.class,int.class); 27 | // m.invoke(addproxy,2,4); 28 | 29 | addproxy.calno(); 30 | } 31 | } -------------------------------------------------------------------------------- /core/src/test/java/com/tg/tiny4j/core/aop/Operate.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop; 2 | 3 | /** 4 | * Created by twogoods on 16/10/24. 5 | */ 6 | public interface Operate { 7 | int cal(int a,int b); 8 | int cal(int a); 9 | int calno(); 10 | } 11 | -------------------------------------------------------------------------------- /core/src/test/java/com/tg/tiny4j/core/aop/TestAopInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.aop; 2 | 3 | import com.tg.tiny4j.core.aop.advice.AopInterceptor; 4 | import com.tg.tiny4j.core.aop.advice.Methodinvocation; 5 | import org.apache.commons.lang3.text.WordUtils; 6 | 7 | import java.lang.reflect.Field; 8 | import java.util.Arrays; 9 | 10 | /** 11 | * Created by twogoods on 16/10/24. 12 | */ 13 | public class TestAopInterceptor implements AopInterceptor { 14 | @Override 15 | public Object invoke(Methodinvocation invocation) throws Throwable { 16 | String methodName=invocation.getMethod().getName(); 17 | if(methodName.startsWith("set")){ 18 | Field f=invocation.getObjClass().getDeclaredField(getFieldNameBySetter(methodName)); 19 | f.setAccessible(true); 20 | f.set(invocation.getTarget(), invocation.getArguments()[0]); 21 | System.out.println("do setter...."); 22 | return null; 23 | } 24 | System.out.println(String.format("***--before--method:{%s},args:{%s}",invocation.getMethod().getName(), Arrays.asList(invocation.getArguments()))); 25 | Object result=invocation.proceed(); 26 | System.out.println(String.format("***--after--result:{%s}",result)); 27 | return result; 28 | } 29 | 30 | private String getFieldNameBySetter(String setterName){ 31 | return WordUtils.uncapitalize(setterName.substring(3)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /core/src/test/java/com/tg/tiny4j/core/ioc/beans/reader/ConfigBean.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.reader; 2 | 3 | import com.tg.tiny4j.core.ioc.annotation.*; 4 | 5 | /** 6 | * Created by twogoods on 16/10/31. 7 | */ 8 | @Component 9 | @Configuration 10 | public class ConfigBean { 11 | 12 | @Value("${user.name:testname}") 13 | private String name; 14 | @Value("${user.pass}") 15 | private String pass; 16 | 17 | @Inject 18 | private ServiceBean serviceBean; 19 | 20 | @Bean 21 | public DaoBean beanAnnDao(){ 22 | System.out.println("in ConfigBean do @Bean method: beanAnnDao"); 23 | return new DaoBean(); 24 | } 25 | 26 | @Bean 27 | public ServiceBean beanAnnService(){ 28 | //new ServiceBean(beanAnnDao()); 还不支持构造器注入 29 | System.out.println("in ConfigBean do @Bean method: beanAnnService"); 30 | ServiceBean newBean=new ServiceBean(); 31 | newBean.setS1(name+"---"+serviceBean.getS1()); 32 | newBean.setS2(pass+"---"+serviceBean.getS2()); 33 | newBean.setDaoBean(beanAnnDao()); 34 | return newBean; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /core/src/test/java/com/tg/tiny4j/core/ioc/beans/reader/DaoBean.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.reader; 2 | 3 | import com.tg.tiny4j.core.ioc.annotation.Component; 4 | 5 | /** 6 | * Created by twogoods on 16/10/29. 7 | */ 8 | @Component 9 | public class DaoBean { 10 | public void execute(){ 11 | System.out.println("sql execute..."); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /core/src/test/java/com/tg/tiny4j/core/ioc/beans/reader/LogBeanPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.reader; 2 | 3 | import com.tg.tiny4j.core.ioc.beans.BeanPostProcessor; 4 | 5 | /** 6 | * Created by twogoods on 16/10/29. 7 | */ 8 | public class LogBeanPostProcessor implements BeanPostProcessor { 9 | @Override 10 | public Object postProcessBeforeInitialization(Object bean, String beanName) { 11 | System.out.println(beanName+" do before..."); 12 | return bean; 13 | } 14 | 15 | @Override 16 | public Object postProcessAfterInitialization(Object bean, String beanName) { 17 | System.out.println(beanName+" do after..."); 18 | return bean; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /core/src/test/java/com/tg/tiny4j/core/ioc/beans/reader/ServiceBean.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.reader; 2 | 3 | import com.tg.tiny4j.core.ioc.annotation.Component; 4 | import com.tg.tiny4j.core.ioc.annotation.Inject; 5 | import com.tg.tiny4j.core.ioc.annotation.Value; 6 | 7 | /** 8 | * Created by twogoods on 16/10/29. 9 | */ 10 | @Component 11 | public class ServiceBean { 12 | @Value("${user.nick:test}") 13 | private String s1; 14 | @Value("${user.name:test}") 15 | private String s2; 16 | 17 | @Inject 18 | private DaoBean daoBean; 19 | 20 | public ServiceBean() { 21 | } 22 | 23 | public ServiceBean(DaoBean daoBean) { 24 | this.daoBean = daoBean; 25 | } 26 | 27 | public void service(){ 28 | daoBean.execute(); 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "ServiceBean{" + 34 | "s1='" + s1 + '\'' + 35 | ", s2='" + s2 + '\'' + 36 | '}'; 37 | } 38 | 39 | public String getS1() { 40 | return s1; 41 | } 42 | 43 | public void setS1(String s1) { 44 | this.s1 = s1; 45 | } 46 | 47 | public String getS2() { 48 | return s2; 49 | } 50 | 51 | public void setS2(String s2) { 52 | this.s2 = s2; 53 | } 54 | 55 | public void setDaoBean(DaoBean daoBean) { 56 | this.daoBean = daoBean; 57 | } 58 | 59 | public DaoBean getDaoBean() { 60 | return daoBean; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /core/src/test/java/com/tg/tiny4j/core/ioc/beans/reader/XmlBeanDefinitionReaderTest.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.beans.reader; 2 | 3 | import org.junit.Test; 4 | 5 | 6 | /** 7 | * Created by twogoods on 16/10/26. 8 | */ 9 | public class XmlBeanDefinitionReaderTest { 10 | 11 | @Test 12 | public void testLoadResource() throws Exception { 13 | XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader("test.xml"); 14 | beanDefinitionReader.loadResource(); 15 | System.out.println(beanDefinitionReader.getRegisterBeans()); 16 | assert beanDefinitionReader.getRegisterBeans().size() > 0; 17 | } 18 | } -------------------------------------------------------------------------------- /core/src/test/java/com/tg/tiny4j/core/ioc/context/ClassPathXmlApplicationContextTest.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.context; 2 | 3 | import com.tg.tiny4j.core.ioc.beans.reader.ConfigBean; 4 | import com.tg.tiny4j.core.ioc.beans.reader.ServiceBean; 5 | import org.junit.Test; 6 | 7 | /** 8 | * Created by twogoods on 16/10/27. 9 | */ 10 | public class ClassPathXmlApplicationContextTest { 11 | @Test 12 | public void test() throws Exception { 13 | System.out.println("1******************"); 14 | ApplicationContext applicationContext = new ClassPathXmlApplicationContext("test.xml"); 15 | 16 | 17 | // ServiceBean serviceBean=(ServiceBean)applicationContext.getBean("testService"); 18 | // System.out.println(serviceBean); 19 | // serviceBean.service(); 20 | 21 | System.out.println("2*******************"); 22 | 23 | // ServiceBean serviceBean2=(ServiceBean)applicationContext.getBean("serviceBean"); 24 | // System.out.println(serviceBean2); 25 | // serviceBean2.service(); 26 | 27 | System.out.println("3*******************"); 28 | 29 | //IOC上下文 30 | // ApplicationContextHolder holder=applicationContext.getBean("applicationContextHolder", ApplicationContextHolder.class); 31 | // System.out.println("holder get bean : "+holder.getBean("serviceBean")); 32 | 33 | System.out.println("4*******************"); 34 | ConfigBean configBean=(ConfigBean)applicationContext.getBean("configBean"); 35 | System.out.println("configbean get dao:"+configBean.beanAnnDao()); 36 | System.out.println("configbean get service:"+configBean.beanAnnService().hashCode()); 37 | ServiceBean beanAnnService=(ServiceBean)applicationContext.getBean("beanAnnService"); 38 | System.out.println("application get service: "+beanAnnService.hashCode()); 39 | System.out.println("application get dao: "+applicationContext.getBean("beanAnnDao")); 40 | beanAnnService.service(); 41 | System.out.println(beanAnnService.getDaoBean().hashCode()+"---"+applicationContext.getBean("beanAnnDao").hashCode()); 42 | 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /core/src/test/java/com/tg/tiny4j/core/ioc/resource/ResourceLoadTest.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.core.ioc.resource; 2 | 3 | import org.junit.Test; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | 8 | /** 9 | * Created by twogoods on 16/10/25. 10 | */ 11 | public class ResourceLoadTest { 12 | @Test 13 | public void test() throws IOException { 14 | Resource resource=ResourceLoad.getInstance().loadResource("test.xml"); 15 | InputStream inputStream=resource.getInputStream(); 16 | byte[] bytes=new byte[1024]; 17 | inputStream.read(bytes); 18 | System.out.println(new String(bytes)); 19 | inputStream.close(); 20 | } 21 | } -------------------------------------------------------------------------------- /core/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | tiny4j.component-scan=com.tg.tiny4j.core.ioc.beans.reader 2 | user.name=twogoods 3 | user.pass=two -------------------------------------------------------------------------------- /core/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /core/src/test/resources/test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | application.properties 5 | ${tiny4j.component-scan:com.tg} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.twogoods.tiny4j 8 | tiny4j 9 | pom 10 | 0.0.1 11 | 12 | rest 13 | web-test 14 | core 15 | commons 16 | web-containerembed 17 | 18 | 19 | 20 | 21 | UTF-8 22 | 1.7 23 | UTF-8 24 | 8.5.5 25 | 26 | 27 | 28 | 29 | junit 30 | junit 31 | 4.12 32 | 33 | 34 | org.slf4j 35 | slf4j-api 36 | 1.7.21 37 | 38 | 39 | org.slf4j 40 | slf4j-simple 41 | 1.7.16 42 | test 43 | 44 | 45 | 46 | 47 | 48 | org.apache.maven.plugins 49 | maven-compiler-plugin 50 | 3.1 51 | 52 | ${java.version} 53 | ${java.version} 54 | UTF-8 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /rest/README.md: -------------------------------------------------------------------------------- 1 | # rest 2 | web框架支持rest,json格式,不提供MVC的V了,基于自己以前的使用经历,会实现SpringMvc里高频的功能以及对一些SpringMvc中不好处理的地方提供更好的支持。 3 | rest模块在设计时就考虑希望可以拆开IOC独立实现,IOC可以单独使用,rest也可以离开IOC单独使用。这样拆开来代码实现也清晰一些,这样我自己实现或者其他同学想了解一个简单的web实现都更容易一些。 4 | ### SpringBoot风格的可执行Jar 5 | SpringBoot以约定大于配置的思想极大的简化了spring项目的配置内容,并提供了一个内嵌容器的可执行Jar,使得部署、管理都更加容易。rest也在尝试模仿SpringBoot的风格,做了一个简化的实现。 6 | #### helloworld 7 | ``` 8 | //boot应用请继承AbstractBootContextListener 9 | public class BootAppLoaderListener extends AbstractBootContextListener { 10 | private static final Logger log = LogManager.getLogger(BootAppLoaderListener.class); 11 | 12 | private final WebAppControllerReader webAppControllerReader = new WebAppControllerReader(); 13 | 14 | @Override 15 | public void registerHandle(HandleRegistry registry) { 16 | HandleAnnotation handle = new HandleAnnotation() { 17 | @Override 18 | public BeanDefinition handle(Class clazz) throws Exception { 19 | BaseInfo baseInfo = webAppControllerReader.read(clazz); 20 | if (Validate.isEmpty(baseInfo)) { 21 | return null; 22 | } else { 23 | return new BeanDefinition(baseInfo.getName(), baseInfo.getClassName()); 24 | } 25 | } 26 | }; 27 | registry.addHandle(handle); 28 | } 29 | 30 | @Override 31 | public void requestMapInitialized(ServletContextEvent servletContextEvent, WebApplicationContext applicationContext) throws Exception { 32 | webAppControllerReader.initRequestMap(); 33 | webAppControllerReader.setInstances(applicationContext.getBeans(webAppControllerReader.getControllerName())); 34 | servletContextEvent.getServletContext().setAttribute(WebApplicationEnvironment.WEBREQUESTMAPPER, webAppControllerReader.getRequestMapper()); 35 | } 36 | } 37 | 38 | @Api 39 | public class Application { 40 | @RequestMapping 41 | public String home() { 42 | return "Hello World!"; 43 | } 44 | public static void main(String[] args) { 45 | TinyApplication.run(BootAppLoaderListener.class, args); 46 | } 47 | } 48 | ``` 49 | 配置`application.properties` 50 | 51 | ``` 52 | tiny4j.component-scan = com.xxx.yyy 53 | tiny4j.server.contextPath = /twogoods 54 | tiny4j.server.port = 8080 55 | ``` 56 | #### 打包 57 | 不造轮子,直接使用SpringBoot的Maven插件(gradle也类似) 58 | 59 | ``` 60 | 61 | 62 | org.springframework.boot 63 | spring-boot-maven-plugin 64 | 1.5.2.RELEASE 65 | 66 | 67 | 68 | repackage 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | 77 | ``` 78 | #### 单独使用 79 | 上面helloworld的代码整合了IOC,如果单独使用直接使用`SingleRestLoaderListener` 80 | 81 | ``` 82 | @Api 83 | public class Application { 84 | @RequestMapping 85 | public String home() { 86 | return "Hello World!"; 87 | } 88 | public static void main(String[] args) { 89 | TinyApplication.run(BootAppLoaderListener.class, args); 90 | } 91 | } 92 | 93 | ``` 94 | 更多请参考`web-containerembed`测试模块。 95 | ### 传统的war形式 96 | #### 单独模式 97 | 即脱离IOC单独使用rest,所有的配置都在web.xml里 98 | 99 | ``` 100 | 101 | 102 | 103 | component-scan 104 | com.tg.web.controller,com.tg.web.base 105 | 106 | 107 | 108 | com.tg.tiny4j.web.contextlistener.SingleRestLoaderListener 109 | 110 | 111 | 112 | dispatcherServlet 113 | com.tg.tiny4j.web.servlet.DispatcherServlet 114 | 115 | 116 | 117 | dispatcherServlet 118 | / 119 | 120 | 121 | ``` 122 | #### 整合模式 123 | 配合IOC使用,导入core模块依赖,继承`AbstractWebContextListener`完成自己的`ContextListener`(复制下面代码即可) 124 | 125 | ``` 126 | public class WebAppLoaderListener extends AbstractWebContextListener { 127 | private final WebAppControllerReader webAppControllerReader = new WebAppControllerReader(); 128 | 129 | @Override 130 | public void registerHandle(HandleRegistry registry) { 131 | HandleAnnotation handle = new HandleAnnotation() { 132 | @Override 133 | public BeanDefinition handle(Class clazz) throws Exception { 134 | BaseInfo baseInfo = webAppControllerReader.read(clazz); 135 | if (Validate.isEmpty(baseInfo)) { 136 | return null; 137 | } else { 138 | return new BeanDefinition(baseInfo.getName(), baseInfo.getClassName()); 139 | } 140 | } 141 | }; 142 | registry.addHandle(handle); 143 | } 144 | 145 | @Override 146 | public void requestMapInitialized(ServletContextEvent servletContextEvent, WebApplicationContext applicationContext) throws Exception { 147 | webAppControllerReader.initRequestMap(); 148 | webAppControllerReader.setInstances(applicationContext.getBean(webAppControllerReader.getControllerName())); 149 | servletContextEvent.getServletContext().setAttribute(WebApplicationEnvironment.WEBREQUESTMAPPER, webAppControllerReader.getRequestMapper()); 150 | } 151 | } 152 | ``` 153 | 相应地在web.xml里配上刚刚创建的`ContextListener`就完成了rest和Ioc的整合,诸如扫描的包等配置,相应的移到application.xml 154 | 155 | ``` 156 | 157 | 158 | 159 | com.xxx.WebAppLoaderListener 160 | 161 | 162 | 163 | dispatcherServlet 164 | com.tg.tiny4j.web.servlet.DispatcherServlet 165 | 166 | 167 | 168 | dispatcherServlet 169 | / 170 | 171 | 172 | ``` 173 | application.xml增加一些config的配置,`Bean`以及更多的配置参见core模块 174 | 175 | ``` 176 | 177 | 178 | 179 | 180 | application.properties 181 | ${tiny4j.component-scan:com.tg.web.controller} 182 | 183 | 184 | ``` 185 | 186 | 187 | ### 具体使用 188 | rest提供了一些注解可以方便的使用,熟悉SpringMvc的同学一看就懂了。`@CROS`加上此注解就可跨域,可以配置请求源,方法等;`@PathVariable`,`@RequestParam`,`@RequestParam`和SpringMvc用法一样;方法返回值会转换成Json输出。 189 | 190 | ``` 191 | @RequestMapping(mapUrl = "/test/{id}", method = HttpMethod.GET) 192 | @CROS(origins = "www.baidu.com", methods = {HttpMethod.GET}, maxAge = "3600") 193 | public Map modelTest(@PathVariable("id") long id, @RequestParam("name") String name, @RequestParam User user) { 194 | Map map = new HashMap<>(); 195 | map.put("name", name); 196 | map.put("id", id); 197 | map.put("user", user); 198 | return map; 199 | } 200 | ``` 201 | `@Interceptor`用于标识一个拦截器,order表示拦截器先后执行顺序(越小越靠前),name默认是类名首字母小写,pathPatterns配置拦截的url。此处拦截器是基于url拦截的,而rest同一个url的不同请求方法的拦截处理这个注解就无法完成。 202 | `@InterceptorSelect`配置响应方法走哪几个拦截器,不走哪几个,这种方式粒度更小,可以确保拦截器被正确执行解决上面的问题,因此**推荐**使用这种配置方法,当然也可以配合`@Interceptor`里的pathPatterns使用。 203 | 204 | ``` 205 | @Interceptor(pathPatterns = {"/base/user"},order = 2) 206 | public class AInterceptor implements HandlerInterceptor{ 207 | @Override 208 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response) { 209 | System.out.println("do A interceptor"); 210 | return true; 211 | } 212 | } 213 | 214 | //controller里的响应方法 215 | @RequestMapping(mapUrl = "/test", method = HttpMethod.GET) 216 | @InterceptorSelect(include = {"aInterceptor"}, exclude = {"bInterceptor"}) 217 | public String interceptorTest() { 218 | return "haha"; 219 | } 220 | ``` 221 | 异常处理也相同 222 | 223 | ``` 224 | @ExceptionHandler(Exception.class) 225 | public String handleException(){ 226 | return "error"; 227 | } 228 | 229 | @RequestMapping(mapUrl = "/exception", method = HttpMethod.GET) 230 | public String exceptionTest() { 231 | int i = 1 / 0; 232 | return "haha"; 233 | } 234 | ``` 235 | 当然,如果你是配合IOC使用的,那IOC支持的都可以无所顾忌的拿来使用 236 | 237 | ``` 238 | @Api("/base") 239 | public class TestController extends BaseController { 240 | 241 | @Value("${user.name:test}") 242 | private String name; 243 | 244 | @Inject 245 | private UserService userService; 246 | 247 | @RequestMapping 248 | public String index() { 249 | userService.query(); 250 | return name; 251 | } 252 | } 253 | ``` 254 | 更多请直接查看[例子](https://github.com/twogoods/tiny4j/tree/master/web-test) -------------------------------------------------------------------------------- /rest/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | tiny4j 7 | com.twogoods.tiny4j 8 | 0.0.1 9 | 10 | 4.0.0 11 | 12 | rest 13 | 14 | 15 | 16 | 17 | com.twogoods.tiny4j 18 | commons 19 | 0.0.1 20 | 21 | 22 | org.eclipse.jetty 23 | jetty-server 24 | 9.4.2.v20170220 25 | 26 | 27 | org.eclipse.jetty 28 | jetty-webapp 29 | 9.4.2.v20170220 30 | 31 | 32 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/annotation/Api.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by twogoods on 16/11/1. 10 | */ 11 | @Target({ElementType.TYPE}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface Api { 14 | String value() default ""; 15 | String name() default ""; 16 | String note() default ""; 17 | } 18 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/annotation/CROS.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.annotation; 2 | 3 | import com.tg.tiny4j.commons.constants.HttpMethod; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * Created by twogoods on 16/11/1. 12 | */ 13 | @Target({ElementType.METHOD,ElementType.TYPE}) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface CROS { 16 | String origins() default "*"; 17 | String[] methods() default {HttpMethod.GET,HttpMethod.POST,HttpMethod.PUT,HttpMethod.PATCH,HttpMethod.DELETE}; 18 | String maxAge() default "3600"; 19 | String headers() default ""; 20 | boolean cookie() default false; 21 | } 22 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/annotation/ComponentScan.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.annotation; 2 | 3 | /** 4 | * Created by twogoods on 16/12/6. 5 | */ 6 | public @interface ComponentScan { 7 | String[] value(); 8 | } 9 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/annotation/ExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by twogoods on 16/11/1. 10 | */ 11 | @Target({ElementType.METHOD}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface ExceptionHandler { 14 | Class value(); 15 | } 16 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/annotation/Interceptor.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by twogoods on 16/11/7. 10 | */ 11 | @Target({ElementType.TYPE}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface Interceptor { 14 | String name() default ""; 15 | String[] pathPatterns() default {}; 16 | String[] excludePathPatterns() default {}; 17 | int order() default 0; 18 | } 19 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/annotation/InterceptorExclude.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by twogoods on 16/11/1. 10 | */ 11 | @Target({ElementType.METHOD}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface InterceptorExclude { 14 | String[] interceptors(); 15 | } 16 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/annotation/InterceptorInclude.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by twogoods on 16/11/1. 10 | */ 11 | @Target({ElementType.METHOD}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface InterceptorInclude { 14 | String[] interceptors(); 15 | } 16 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/annotation/InterceptorSelect.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by twogoods on 16/12/4. 10 | */ 11 | @Target({ElementType.METHOD}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface InterceptorSelect { 14 | String[] include() default {}; 15 | String[] exclude() default {}; 16 | } 17 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/annotation/PathVariable.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by twogoods on 16/11/1. 10 | */ 11 | @Target({ElementType.PARAMETER}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface PathVariable { 14 | String value(); 15 | } 16 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/annotation/RequestBody.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by twogoods on 16/11/1. 10 | */ 11 | @Target({ElementType.PARAMETER}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface RequestBody { 14 | } 15 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/annotation/RequestMapping.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by twogoods on 16/11/1. 10 | */ 11 | @Target({ElementType.METHOD}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface RequestMapping { 14 | String mapUrl() default ""; 15 | String method() default ""; 16 | } 17 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/annotation/RequestParam.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by twogoods on 16/12/2. 10 | */ 11 | @Target({ElementType.PARAMETER}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface RequestParam { 14 | String value() default ""; 15 | } 16 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/contextlistener/SingleRestLoaderListener.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.contextlistener; 2 | 3 | import com.tg.tiny4j.commons.constants.WebApplicationEnvironment; 4 | import com.tg.tiny4j.web.reader.ConfigLoader; 5 | import com.tg.tiny4j.web.reader.WebScanedClassReader; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import javax.servlet.ServletContextEvent; 11 | import javax.servlet.ServletContextListener; 12 | 13 | /** 14 | * Created by twogoods on 16/11/2. 15 | */ 16 | public class SingleRestLoaderListener implements ServletContextListener { 17 | private static Logger log = LoggerFactory.getLogger(SingleRestLoaderListener.class); 18 | 19 | @Override 20 | public void contextInitialized(ServletContextEvent servletContextEvent) { 21 | //TODO 去掉Web.xml下的包配置,使用注解? 22 | log.info("contextInit..."); 23 | try { 24 | String packages = ConfigLoader.loadConfig().getComponentscan(); 25 | if (StringUtils.isEmpty(packages)) { 26 | packages = servletContextEvent.getServletContext().getInitParameter("component-scan"); 27 | } 28 | log.debug("auto package: {}", packages); 29 | WebScanedClassReader webScanedClassReader = new WebScanedClassReader(); 30 | webScanedClassReader.loadClass(packages); 31 | webScanedClassReader.initRequestMap(); 32 | webScanedClassReader.instance4SingleMode(); 33 | servletContextEvent.getServletContext().setAttribute(WebApplicationEnvironment.RUN_MODE, WebApplicationEnvironment.SINGLE_MODE); 34 | servletContextEvent.getServletContext().setAttribute(WebApplicationEnvironment.WEBREQUESTMAPPER, webScanedClassReader.getRequestMapper()); 35 | } catch (Exception e) { 36 | log.error("start rest failed", e); 37 | } 38 | } 39 | 40 | @Override 41 | public void contextDestroyed(ServletContextEvent servletContextEvent) { 42 | log.info("SingleRestLoaderListener destroyed..."); 43 | } 44 | } -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/exception/ConfigurationException.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.exception; 2 | 3 | /** 4 | * Description: 5 | * 6 | * @author twogoods 7 | * @version 0.1 8 | * @since 2017-03-13 9 | */ 10 | public class ConfigurationException extends Exception{ 11 | public ConfigurationException(String message) { 12 | super(message); 13 | } 14 | 15 | public ConfigurationException(String message, Throwable cause) { 16 | super(message, cause); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/exception/ExceptionHandleException.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.exception; 2 | 3 | /** 4 | * Created by twogoods on 16/11/8. 5 | */ 6 | public class ExceptionHandleException extends Exception{ 7 | 8 | public ExceptionHandleException(String message) { 9 | super(message); 10 | } 11 | 12 | public ExceptionHandleException(String message, Throwable cause) { 13 | super(message, cause); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/exception/InterceptorDuplicatedException.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.exception; 2 | 3 | /** 4 | * Created by twogoods on 16/11/9. 5 | */ 6 | public class InterceptorDuplicatedException extends Exception{ 7 | public InterceptorDuplicatedException(String message) { 8 | super(message); 9 | } 10 | 11 | public InterceptorDuplicatedException(String message, Throwable cause) { 12 | super(message, cause); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/exception/UrlDuplicatedException.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.exception; 2 | 3 | 4 | /** 5 | * Created by twogoods on 16/12/3. 6 | */ 7 | public class UrlDuplicatedException extends Exception{ 8 | public UrlDuplicatedException(String message) { 9 | super(message); 10 | } 11 | 12 | public UrlDuplicatedException(String message, Throwable cause) { 13 | super(message, cause); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/handle/RequestHandleMapping.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.handle; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | import javax.servlet.http.HttpServletResponse; 5 | 6 | /** 7 | * Created by twogoods on 16/11/10. 8 | */ 9 | public class RequestHandleMapping { 10 | 11 | public static void handle(HttpServletRequest req, HttpServletResponse resp){ 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/integration/WebAppControllerReader.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.integration; 2 | 3 | import com.tg.tiny4j.web.metadata.ControllerInfo; 4 | import com.tg.tiny4j.web.metadata.InterceptorInfo; 5 | import com.tg.tiny4j.web.reader.AbstractClassReader; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | /** 12 | * Created by twogoods on 16/11/2. 13 | */ 14 | public class WebAppControllerReader extends AbstractClassReader { 15 | 16 | public List getControllerName() { 17 | List objNamesList=new ArrayList<>(); 18 | Map controllerInfoMap = getRequestMapper().getApis(); 19 | for (String key : controllerInfoMap.keySet()) { 20 | objNamesList.add(controllerInfoMap.get(key).getName()); 21 | } 22 | for (InterceptorInfo interceptor : getRequestMapper().getInterceptorList()) { 23 | objNamesList.add(interceptor.getName()); 24 | } 25 | return objNamesList; 26 | } 27 | 28 | public void setInstances(Map instances){ 29 | Map controllerInfoMap = getRequestMapper().getApis(); 30 | for (String key : controllerInfoMap.keySet()) { 31 | controllerInfoMap.get(key).setObject(instances.get(key)); 32 | } 33 | for (InterceptorInfo interceptor : getRequestMapper().getInterceptorList()) { 34 | interceptor.setObj(instances.get(interceptor.getName())); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/interceptor/HandlerInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.interceptor; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | import javax.servlet.http.HttpServletResponse; 5 | 6 | /** 7 | * Created by twogoods on 16/11/7. 8 | */ 9 | public interface HandlerInterceptor { 10 | boolean preHandle(HttpServletRequest request, HttpServletResponse response); 11 | } 12 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/jettyembed/Configuration.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.jettyembed; 2 | 3 | /** 4 | * Description: 5 | * 6 | * @author twogoods 7 | * @version 0.1 8 | * @since 2017-03-31 9 | */ 10 | public class Configuration { 11 | private String componentscan; 12 | private String contextPath = "twogoods"; 13 | private int port = 8080; 14 | 15 | public String getComponentscan() { 16 | return componentscan; 17 | } 18 | 19 | public void setComponentscan(String componentscan) { 20 | this.componentscan = componentscan; 21 | } 22 | 23 | public String getContextPath() { 24 | return contextPath; 25 | } 26 | 27 | public void setContextPath(String contextPath) { 28 | this.contextPath = contextPath; 29 | } 30 | 31 | public int getPort() { 32 | return port; 33 | } 34 | 35 | public void setPort(int port) { 36 | this.port = port; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/jettyembed/TinyApplication.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.jettyembed; 2 | 3 | import com.tg.tiny4j.web.reader.ConfigLoader; 4 | import com.tg.tiny4j.web.servlet.DispatcherServlet; 5 | import org.eclipse.jetty.server.Server; 6 | import org.eclipse.jetty.servlet.ServletContextHandler; 7 | 8 | import java.util.EventListener; 9 | 10 | /** 11 | * Description: 12 | * 13 | * @author twogoods 14 | * @version 0.1 15 | * @since 2017-03-31 16 | */ 17 | public class TinyApplication { 18 | public static void run(Class listener, String[] args) { 19 | try { 20 | Configuration configuration = ConfigLoader.loadConfig(); 21 | Server server = new Server(configuration.getPort()); 22 | ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); 23 | context.setContextPath(configuration.getContextPath()); 24 | context.addEventListener(listener.newInstance()); 25 | context.addServlet(DispatcherServlet.class, "/*"); 26 | server.setHandler(context); 27 | server.start(); 28 | server.join(); 29 | } catch (Exception e) { 30 | throw new RuntimeException(e); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/metadata/BaseInfo.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.metadata; 2 | 3 | /** 4 | * Created by twogoods on 16/11/9. 5 | */ 6 | public class BaseInfo { 7 | protected String name; 8 | protected String className; 9 | protected Class clazz; 10 | 11 | public String getName() { 12 | return name; 13 | } 14 | 15 | public void setName(String name) { 16 | this.name = name; 17 | } 18 | 19 | public String getClassName() { 20 | return className; 21 | } 22 | 23 | public void setClassName(String className) { 24 | this.className = className; 25 | } 26 | 27 | public Class getClazz() { 28 | return clazz; 29 | } 30 | 31 | public void setClazz(Class clazz) { 32 | this.clazz = clazz; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/metadata/ControllerInfo.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.metadata; 2 | 3 | /** 4 | * Created by twogoods on 16/11/2. 5 | */ 6 | public class ControllerInfo extends BaseInfo{ 7 | private Object object; 8 | 9 | public Object getObject() { 10 | return object; 11 | } 12 | 13 | public void setObject(Object object) { 14 | this.object = object; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/metadata/CrosInfo.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.metadata; 2 | 3 | /** 4 | * Created by twogoods on 16/12/3. 5 | */ 6 | public class CrosInfo { 7 | private String origins; 8 | private String[] methods; 9 | private String maxAge; 10 | private String headers; 11 | private boolean cookie; 12 | 13 | public CrosInfo() { 14 | } 15 | 16 | public CrosInfo(String origins, String[] methods, String maxAge, String headers, boolean cookie) { 17 | this.origins = origins; 18 | this.methods = methods; 19 | this.maxAge = maxAge; 20 | this.headers = headers; 21 | this.cookie = cookie; 22 | } 23 | 24 | public String getOrigins() { 25 | return origins; 26 | } 27 | 28 | public void setOrigins(String origins) { 29 | this.origins = origins; 30 | } 31 | 32 | public String[] getMethods() { 33 | return methods; 34 | } 35 | 36 | public void setMethods(String[] methods) { 37 | this.methods = methods; 38 | } 39 | 40 | public String getMaxAge() { 41 | return maxAge; 42 | } 43 | 44 | public void setMaxAge(String maxAge) { 45 | this.maxAge = maxAge; 46 | } 47 | 48 | public String getHeaders() { 49 | return headers; 50 | } 51 | 52 | public void setHeaders(String headers) { 53 | this.headers = headers; 54 | } 55 | 56 | public boolean isCookie() { 57 | return cookie; 58 | } 59 | 60 | public void setCookie(boolean cookie) { 61 | this.cookie = cookie; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/metadata/ExceptionHandleInfo.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.metadata; 2 | 3 | 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * Created by twogoods on 16/11/8. 8 | */ 9 | public class ExceptionHandleInfo { 10 | private String beanName; 11 | private String exceptionName; 12 | private Method method; 13 | 14 | public ExceptionHandleInfo() { 15 | } 16 | 17 | public ExceptionHandleInfo(String beanName, String exceptionName, Method method) { 18 | this.beanName = beanName; 19 | this.exceptionName = exceptionName; 20 | this.method = method; 21 | } 22 | 23 | public String getExceptionName() { 24 | return exceptionName; 25 | } 26 | 27 | public void setExceptionName(String exceptionName) { 28 | this.exceptionName = exceptionName; 29 | } 30 | 31 | public Method getMethod() { 32 | return method; 33 | } 34 | 35 | public void setMethod(Method method) { 36 | this.method = method; 37 | } 38 | 39 | public String getBeanName() { 40 | return beanName; 41 | } 42 | 43 | public void setBeanName(String beanName) { 44 | this.beanName = beanName; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/metadata/InterceptorInfo.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.metadata; 2 | 3 | /** 4 | * Created by twogoods on 16/11/7. 5 | */ 6 | public class InterceptorInfo extends BaseInfo{ 7 | private Object obj; 8 | private String[] pathPatterns; 9 | private String[] excludePathPatterns; 10 | int order; 11 | 12 | 13 | public String[] getPathPatterns() { 14 | return pathPatterns; 15 | } 16 | 17 | public void setPathPatterns(String[] pathPatterns) { 18 | this.pathPatterns = pathPatterns; 19 | } 20 | 21 | public String[] getExcludePathPatterns() { 22 | return excludePathPatterns; 23 | } 24 | 25 | public void setExcludePathPatterns(String[] excludePathPatterns) { 26 | this.excludePathPatterns = excludePathPatterns; 27 | } 28 | 29 | public int getOrder() { 30 | return order; 31 | } 32 | 33 | public void setOrder(int order) { 34 | this.order = order; 35 | } 36 | 37 | public Object getObj() { 38 | return obj; 39 | } 40 | 41 | public void setObj(Object obj) { 42 | this.obj = obj; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/metadata/RequestHandleInfo.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.metadata; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.*; 5 | 6 | /** 7 | * Created by twogoods on 16/11/2. 8 | */ 9 | public class RequestHandleInfo { 10 | /** 11 | * url,controller对象,方法,请求方法,拦截器信息 12 | * url对应一个请求方法 13 | * 在一个map,存controller对象,或者ioc里拿 14 | */ 15 | private String methodName; 16 | private Method method; 17 | private String className; 18 | private String beanName; 19 | private Object instance; 20 | private String requestUrl; 21 | private String requestmethod; 22 | private UrlPraseInfo urlPraseInfo; 23 | private CrosInfo cros; 24 | private List includeInterceptors = new ArrayList<>(); 25 | private List excludeInterceptors = new ArrayList<>(); 26 | private Map doInterceptors = new HashMap<>(); 27 | 28 | public String getMethodName() { 29 | return methodName; 30 | } 31 | 32 | public void setMethodName(String methodName) { 33 | this.methodName = methodName; 34 | } 35 | 36 | public Method getMethod() { 37 | return method; 38 | } 39 | 40 | public void setMethod(Method method) { 41 | this.method = method; 42 | } 43 | 44 | public String getClassName() { 45 | return className; 46 | } 47 | 48 | public void setClassName(String className) { 49 | this.className = className; 50 | } 51 | 52 | public String getBeanName() { 53 | return beanName; 54 | } 55 | 56 | public void setBeanName(String beanName) { 57 | this.beanName = beanName; 58 | } 59 | 60 | public Object getInstance() { 61 | return instance; 62 | } 63 | 64 | public void setInstance(Object instance) { 65 | this.instance = instance; 66 | } 67 | 68 | public String getRequestUrl() { 69 | return requestUrl; 70 | } 71 | 72 | public void setRequestUrl(String requestUrl) { 73 | this.requestUrl = requestUrl; 74 | } 75 | 76 | public String getRequestmethod() { 77 | return requestmethod; 78 | } 79 | 80 | public void setRequestmethod(String requestmethod) { 81 | this.requestmethod = requestmethod; 82 | } 83 | 84 | public UrlPraseInfo getUrlPraseInfo() { 85 | return urlPraseInfo; 86 | } 87 | 88 | public void setUrlPraseInfo(UrlPraseInfo urlPraseInfo) { 89 | this.urlPraseInfo = urlPraseInfo; 90 | } 91 | 92 | public CrosInfo getCros() { 93 | return cros; 94 | } 95 | 96 | public void setCros(CrosInfo cros) { 97 | this.cros = cros; 98 | } 99 | 100 | public List getIncludeInterceptors() { 101 | return includeInterceptors; 102 | } 103 | 104 | public void setIncludeInterceptors(String[] includeInterceptors) { 105 | this.includeInterceptors.addAll(Arrays.asList(includeInterceptors)); 106 | } 107 | 108 | public void setExcludeInterceptors(String[] excludeInterceptors) { 109 | this.excludeInterceptors.addAll(Arrays.asList(excludeInterceptors)); 110 | } 111 | 112 | public List getExcludeInterceptors() { 113 | return excludeInterceptors; 114 | } 115 | 116 | public Map getDoInterceptors() { 117 | return doInterceptors; 118 | } 119 | 120 | public void addDoInterceptors(String interceptor) { 121 | this.doInterceptors.put(interceptor, interceptor); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/metadata/RequestMapper.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.metadata; 2 | 3 | import com.tg.tiny4j.web.exception.ExceptionHandleException; 4 | import com.tg.tiny4j.web.exception.InterceptorDuplicatedException; 5 | import com.tg.tiny4j.web.exception.UrlDuplicatedException; 6 | 7 | import java.util.*; 8 | 9 | /** 10 | * Created by twogoods on 16/11/8. 11 | */ 12 | public class RequestMapper { 13 | //Controller 类信息和实例化的对象 14 | private Map apis = new HashMap<>(); 15 | //拦截器信息 16 | private Map interceptors = new HashMap<>(); 17 | //list的顺序就是拦截顺序 18 | private List interceptorList = new ArrayList<>(); 19 | //处理请求的信息 20 | private Map requestHandleMap = new HashMap<>(); 21 | 22 | private List urlPraseResult = new ArrayList<>(); 23 | 24 | //异常信息 25 | private Map> exceptionHandles = new HashMap<>(); 26 | 27 | public void sortInterceptorList() { 28 | Collections.sort(interceptorList, new Comparator() { 29 | @Override 30 | public int compare(InterceptorInfo o1, InterceptorInfo o2) { 31 | return o1.getOrder() - o2.getOrder(); 32 | } 33 | }); 34 | } 35 | 36 | public void addApis(String name, ControllerInfo controllerInfo) { 37 | this.apis.put(name, controllerInfo); 38 | } 39 | 40 | public void addInterceptorList(InterceptorInfo interceptorInfo) { 41 | this.interceptorList.add(interceptorInfo); 42 | } 43 | 44 | public void addRequestHandleMap(String url, RequestHandleInfo requestHandleInfo) throws UrlDuplicatedException { 45 | if (this.requestHandleMap.putIfAbsent(url, requestHandleInfo) != null) { 46 | throw new UrlDuplicatedException(String.format("check duplicated url : '%s'", url.replace("\\w*", "**"))); 47 | } 48 | } 49 | 50 | public void addExceptionHandle(String className, ExceptionHandleInfo exceptionHandleInfo) throws ExceptionHandleException { 51 | Map map = exceptionHandles.get(className); 52 | if (map == null) { 53 | map = new HashMap<>(); 54 | map.put(exceptionHandleInfo.getExceptionName(), exceptionHandleInfo); 55 | exceptionHandles.put(className, map); 56 | } else { 57 | if (map.putIfAbsent(exceptionHandleInfo.getExceptionName(), exceptionHandleInfo) != null) { 58 | throw new ExceptionHandleException(String.format("%s duplicated exceptionhandle for '%s'", className, exceptionHandleInfo.getExceptionName())); 59 | } 60 | } 61 | } 62 | 63 | public Map getApis() { 64 | return apis; 65 | } 66 | 67 | public void addInterceptors(String name, InterceptorInfo interceptor) throws InterceptorDuplicatedException { 68 | if (this.interceptors.put(name, interceptor) != null) { 69 | throw new InterceptorDuplicatedException(String.format("name '%s' is Duplicated, check interceptor '%s'", name, interceptor.getClassName())); 70 | } 71 | } 72 | 73 | public Map getInterceptors() { 74 | return interceptors; 75 | } 76 | 77 | public List getInterceptorList() { 78 | return interceptorList; 79 | } 80 | 81 | public Map getRequestHandleMap() { 82 | return requestHandleMap; 83 | } 84 | 85 | public Map> getExceptionHandles() { 86 | return exceptionHandles; 87 | } 88 | 89 | public List getUrlPraseResult() { 90 | return urlPraseResult; 91 | } 92 | 93 | public void addUrlPraseResult(String prasedUrl) throws UrlDuplicatedException { 94 | for (String s : urlPraseResult) { 95 | if (s.equals(prasedUrl)) { 96 | throw new UrlDuplicatedException(String.format("url duplicated ! two url: '%s' , '%s'", prasedUrl.replace("\\w*", "**"), s.replace("\\w*", "**"))); 97 | } 98 | } 99 | urlPraseResult.add(prasedUrl); 100 | } 101 | 102 | @Override 103 | public String toString() { 104 | return "RequestMapper{" + 105 | "apis=" + apis + 106 | ", interceptors=" + interceptors + 107 | ", interceptorList=" + interceptorList + 108 | ", requestHandleMap=" + requestHandleMap + 109 | ", exceptionHandles=" + exceptionHandles + 110 | '}'; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/metadata/UrlPraseInfo.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.metadata; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by twogoods on 16/12/3. 7 | */ 8 | public class UrlPraseInfo { 9 | private String match; 10 | private List params; 11 | 12 | public UrlPraseInfo() { 13 | } 14 | 15 | public UrlPraseInfo(String match, List params) { 16 | this.match = match; 17 | this.params = params; 18 | } 19 | 20 | public String getMatch() { 21 | return match; 22 | } 23 | 24 | public void setMatch(String match) { 25 | this.match = match; 26 | } 27 | 28 | public List getParams() { 29 | return params; 30 | } 31 | 32 | public void setParams(List params) { 33 | this.params = params; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/reader/ClassScanner.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.reader; 2 | 3 | import org.apache.commons.io.IOUtils; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.io.File; 9 | import java.io.FileNotFoundException; 10 | import java.io.IOException; 11 | import java.net.JarURLConnection; 12 | import java.net.URL; 13 | import java.net.URLConnection; 14 | import java.net.URLDecoder; 15 | import java.util.Enumeration; 16 | import java.util.HashSet; 17 | import java.util.List; 18 | import java.util.Set; 19 | import java.util.jar.JarEntry; 20 | import java.util.jar.JarFile; 21 | import java.util.jar.JarInputStream; 22 | 23 | /** 24 | * Created by twogoods on 16/10/28. 25 | */ 26 | public class ClassScanner { 27 | private static final Logger log = LoggerFactory.getLogger(ClassScanner.class); 28 | public static Set getClasses(String[] packages) throws Exception { 29 | Set classes = new HashSet(); 30 | for (String packageName : packages) { 31 | if (StringUtils.isEmpty(packageName)) { 32 | continue; 33 | } 34 | getClassByPackage(packageName.replace(".", File.separator), classes); 35 | } 36 | return classes; 37 | } 38 | 39 | private static void getClassByPackage(String packageName, Set classes) throws Exception { 40 | Enumeration baseURLs = ClassScanner.class.getClassLoader().getResources(packageName); 41 | URL baseURL = null; 42 | while (baseURLs.hasMoreElements()) { 43 | baseURL = baseURLs.nextElement(); 44 | if (baseURL != null) { 45 | log.debug("componentscan find: {}",baseURL.toString()); 46 | String protocol = baseURL.getProtocol(); 47 | String basePath = baseURL.getFile(); 48 | if ("jar".equals(protocol)) { 49 | //实际运行中看到了这样的形式的jar目录 /BOOT-INF/classes!/com ,classes是一个目录,去掉后面的!,原因还没弄明白. 50 | basePath = basePath.replace("classes!", "classes"); 51 | String[] paths = basePath.split("jar!/"); 52 | if (paths.length == 2) { 53 | findFileInJar(paths[0] + "jar!/", paths[1], classes); 54 | } else if (paths.length > 2) { 55 | int index = basePath.lastIndexOf("jar!/") + "jar".length(); 56 | String lastJarPath = basePath.substring(0, index); 57 | String packagepath = basePath.substring(index + "!/".length(), basePath.length()); 58 | findFileInJarWithinJar(lastJarPath, packagepath, classes); 59 | } 60 | } else { 61 | getClassesInFile(basePath, packageName, classes); 62 | } 63 | } 64 | } 65 | } 66 | 67 | private static void findFileInJar(String filePath, String packagePath, Set classes) throws IOException { 68 | URL url = new URL("jar", null, 0, filePath); 69 | URLConnection con = url.openConnection(); 70 | if (con instanceof JarURLConnection) { 71 | JarURLConnection result = (JarURLConnection) con; 72 | JarFile jarFile = result.getJarFile(); 73 | for (final Enumeration enumJar = jarFile.entries(); enumJar.hasMoreElements(); ) { 74 | JarEntry entry = enumJar.nextElement(); 75 | filterClass(entry.getName(), packagePath, classes); 76 | } 77 | jarFile.close(); 78 | } 79 | } 80 | 81 | private static void findFileInJarWithinJar(String filePath, String packagePath, Set classes) throws IOException { 82 | URL url = new URL("jar", null, 0, filePath); 83 | URLConnection con = url.openConnection(); 84 | if (con instanceof JarURLConnection) { 85 | JarURLConnection jarURLConnection = (JarURLConnection) con; 86 | JarInputStream jarInputStream = new JarInputStream(jarURLConnection.getInputStream()); 87 | JarEntry entry; 88 | while ((entry = jarInputStream.getNextJarEntry()) != null) { 89 | filterClass(entry.getName(), packagePath, classes); 90 | } 91 | IOUtils.closeQuietly(jarInputStream); 92 | } 93 | } 94 | 95 | private static void filterClass(String filePath, String packageName, Set classes) { 96 | if (filePath.startsWith(packageName) && filePath.endsWith(".class")) { 97 | classes.add(getWholeClassName(filePath)); 98 | } 99 | } 100 | 101 | 102 | public static void getClassesInFile(String filePath, String packagePath, Set classes) throws Exception { 103 | File file = new File(filePath); 104 | if (!file.exists()) { 105 | throw new FileNotFoundException("check component-scan config, file or directory not found, path is " + filePath); 106 | } 107 | for (String fileName : file.list()) { 108 | String childFilePath = filePath; 109 | if (filePath.endsWith("/")) { 110 | childFilePath = childFilePath + fileName; 111 | } else { 112 | childFilePath = childFilePath + File.separator + fileName; 113 | } 114 | if (new File(childFilePath).isDirectory()) { 115 | getClassesInFile(childFilePath, packagePath, classes); 116 | } else if (fileName.endsWith(".class")) { 117 | String className = getWholeClassName(childFilePath); 118 | classes.add(className); 119 | } 120 | } 121 | } 122 | 123 | private static String getWholeClassName(String filePath) { 124 | if (filePath.indexOf("classes/") != -1) { 125 | return filePath.substring(filePath.indexOf("classes/") + "classes/".length(), 126 | filePath.indexOf(".class")).replaceAll("/", "."); 127 | } 128 | return filePath.substring(0, filePath.indexOf(".class")).replaceAll("/", "."); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/reader/ConfigLoader.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.reader; 2 | 3 | import com.tg.tiny4j.commons.constants.ConfigurationElement; 4 | import com.tg.tiny4j.web.exception.ConfigurationException; 5 | import com.tg.tiny4j.web.jettyembed.Configuration; 6 | import org.apache.commons.io.IOUtils; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import java.io.InputStream; 11 | import java.util.Enumeration; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | import java.util.Properties; 15 | 16 | /** 17 | * Description: 18 | * 19 | * @author twogoods 20 | * @version 0.1 21 | * @since 2017-03-13 22 | */ 23 | public class ConfigLoader { 24 | private static final Logger log = LoggerFactory.getLogger(ConfigLoader.class); 25 | 26 | 27 | private ConfigLoader() { 28 | } 29 | 30 | public static Configuration loadConfig() throws Exception { 31 | return loadConfig(ConfigurationElement.DEFAULT_CONFIG_FILE); 32 | } 33 | 34 | public static Configuration loadConfig(String name) throws Exception { 35 | Configuration configuration = new Configuration(); 36 | InputStream in = ConfigLoader.class.getClassLoader().getResourceAsStream(name); 37 | if (in == null) { 38 | throw new ConfigurationException(String.format("'%s' is not exist", name)); 39 | } 40 | try { 41 | Properties prop = new Properties(); 42 | prop.load(in); 43 | Enumeration en = prop.propertyNames(); 44 | while (en.hasMoreElements()) { 45 | String strKey = (String) en.nextElement(); 46 | log.debug("get config : {} = {}", strKey, prop.getProperty(strKey)); 47 | if (ConfigurationElement.COMPONENTSCAN.equals(strKey)) { 48 | configuration.setComponentscan(prop.getProperty(strKey)); 49 | } else if (ConfigurationElement.SERVER_CONTEXTPATH.equals(strKey)) { 50 | configuration.setContextPath(prop.getProperty(strKey)); 51 | } else if (ConfigurationElement.SERVER_PORT.equals(strKey)) { 52 | configuration.setPort(Integer.valueOf(prop.getProperty(strKey))); 53 | } 54 | } 55 | } finally { 56 | IOUtils.closeQuietly(in); 57 | } 58 | return configuration; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/reader/Reader.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.reader; 2 | 3 | import com.tg.tiny4j.web.metadata.BaseInfo; 4 | import com.tg.tiny4j.web.metadata.ControllerInfo; 5 | import com.tg.tiny4j.web.metadata.RequestHandleInfo; 6 | import com.tg.tiny4j.web.metadata.RequestMapper; 7 | 8 | import java.util.Map; 9 | 10 | /** 11 | * Created by twogoods on 16/11/2. 12 | */ 13 | public interface Reader { 14 | BaseInfo read(Class clazz) throws Exception; 15 | 16 | RequestMapper getRequestMapper(); 17 | } 18 | -------------------------------------------------------------------------------- /rest/src/main/java/com/tg/tiny4j/web/reader/WebScanedClassReader.java: -------------------------------------------------------------------------------- 1 | package com.tg.tiny4j.web.reader; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.io.FileNotFoundException; 8 | import java.util.HashSet; 9 | import java.util.Set; 10 | 11 | /** 12 | * Created by twogoods on 16/11/2. 13 | */ 14 | public class WebScanedClassReader extends AbstractClassReader { 15 | private static Logger log = LoggerFactory.getLogger(WebScanedClassReader.class); 16 | 17 | Set classSet = new HashSet<>(); 18 | 19 | public void loadClass(String packageConfig) { 20 | if (StringUtils.isEmpty(packageConfig)) { 21 | return; 22 | } 23 | try { 24 | Set classes = ClassScanner.getClasses(packageConfig.split(",")); 25 | log.debug("get class:{}", classes); 26 | loadClasses(classes); 27 | for (Class clazz : classSet) { 28 | read(clazz); 29 | } 30 | } catch (Exception e) { 31 | log.error("loadclass error:{}", e); 32 | throw new RuntimeException(e); 33 | } 34 | } 35 | 36 | private void loadClasses(Set classes) throws ClassNotFoundException { 37 | for (String className : classes) { 38 | classSet.add(Class.forName(className)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /web-containerembed/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | tiny4j 7 | com.twogoods.tiny4j 8 | 0.0.1 9 | 10 | 4.0.0 11 | 12 | web-containerembed 13 | jar 14 | 15 | 16 | 17 | com.twogoods.tiny4j 18 | rest 19 | 0.0.1 20 | 21 | 22 | com.twogoods.tiny4j 23 | core 24 | 0.0.1 25 | 26 | 27 | 28 | org.apache.tomcat.embed 29 | tomcat-embed-core 30 | ${tomcat.version} 31 | 32 | 33 | org.apache.tomcat.embed 34 | tomcat-embed-el 35 | ${tomcat.version} 36 | 37 | 38 | org.apache.tomcat.embed 39 | tomcat-embed-jasper 40 | ${tomcat.version} 41 | 42 | 43 | org.apache.tomcat.embed 44 | tomcat-embed-websocket 45 | ${tomcat.version} 46 | 47 | 48 | org.apache.tomcat 49 | tomcat-jdbc 50 | ${tomcat.version} 51 | 52 | 53 | org.apache.tomcat 54 | tomcat-jsp-api 55 | ${tomcat.version} 56 | 57 | 58 | 59 | org.apache.logging.log4j 60 | log4j-core 61 | 2.7 62 | 63 | 64 | org.apache.logging.log4j 65 | log4j-api 66 | 2.7 67 | 68 | 69 | org.apache.logging.log4j 70 | log4j-slf4j-impl 71 | 2.8 72 | 73 | 74 | org.apache.logging.log4j 75 | log4j-jcl 76 | 2.8 77 | 78 | 79 | 80 | 81 | web-innerjttty 82 | 83 | 84 | org.springframework.boot 85 | spring-boot-maven-plugin 86 | 1.5.2.RELEASE 87 | 88 | 89 | 90 | repackage 91 | 92 | 93 | 94 | 95 | true 96 | 97 | 98 | 99 | org.apache.maven.plugins 100 | maven-surefire-plugin 101 | 102 | true 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /web-containerembed/src/main/java/com/tg/web/Application.java: -------------------------------------------------------------------------------- 1 | package com.tg.web; 2 | 3 | import com.tg.tiny4j.web.annotation.Api; 4 | import com.tg.tiny4j.web.annotation.RequestMapping; 5 | import com.tg.tiny4j.web.contextlistener.SingleRestLoaderListener; 6 | import com.tg.tiny4j.web.jettyembed.TinyApplication; 7 | import com.tg.web.contextlistener.BootAppLoaderListener; 8 | 9 | /** 10 | * Description: 11 | * 12 | * @author twogoods 13 | * @version 0.1 14 | * @since 2017-03-31 15 | */ 16 | @Api 17 | public class Application { 18 | @RequestMapping 19 | public String home() { 20 | return "Hello World!"; 21 | } 22 | public static void main(String[] args) { 23 | //TinyApplication.run(SingleRestLoaderListener.class, args); 24 | TinyApplication.run(BootAppLoaderListener.class, args); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /web-containerembed/src/main/java/com/tg/web/contextlistener/BootAppLoaderListener.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.contextlistener; 2 | 3 | import com.tg.tiny4j.commons.constants.WebApplicationEnvironment; 4 | import com.tg.tiny4j.commons.utils.Validate; 5 | import com.tg.tiny4j.core.ioc.beans.BeanDefinition; 6 | import com.tg.tiny4j.core.web.integration.ContextListener.AbstractBootContextListener; 7 | import com.tg.tiny4j.core.web.integration.HandleAnnotation; 8 | import com.tg.tiny4j.core.web.integration.HandleRegistry; 9 | import com.tg.tiny4j.core.web.integration.context.WebApplicationContext; 10 | import com.tg.tiny4j.web.integration.WebAppControllerReader; 11 | import com.tg.tiny4j.web.metadata.BaseInfo; 12 | import org.apache.logging.log4j.LogManager; 13 | import org.apache.logging.log4j.Logger; 14 | 15 | import javax.servlet.ServletContextEvent; 16 | 17 | /** 18 | * Description: 19 | * 20 | * @author twogoods 21 | * @version 0.1 22 | * @since 2017-03-31 23 | */ 24 | public class BootAppLoaderListener extends AbstractBootContextListener { 25 | private static final Logger log = LogManager.getLogger(BootAppLoaderListener.class); 26 | 27 | private final WebAppControllerReader webAppControllerReader = new WebAppControllerReader(); 28 | 29 | @Override 30 | public void registerHandle(HandleRegistry registry) { 31 | HandleAnnotation handle = new HandleAnnotation() { 32 | @Override 33 | public BeanDefinition handle(Class clazz) throws Exception { 34 | BaseInfo baseInfo = webAppControllerReader.read(clazz); 35 | if (Validate.isEmpty(baseInfo)) { 36 | return null; 37 | } else { 38 | return new BeanDefinition(baseInfo.getName(), baseInfo.getClassName()); 39 | } 40 | } 41 | }; 42 | registry.addHandle(handle); 43 | } 44 | 45 | @Override 46 | public void requestMapInitialized(ServletContextEvent servletContextEvent, WebApplicationContext applicationContext) throws Exception { 47 | webAppControllerReader.initRequestMap(); 48 | webAppControllerReader.setInstances(applicationContext.getBeans(webAppControllerReader.getControllerName())); 49 | servletContextEvent.getServletContext().setAttribute(WebApplicationEnvironment.WEBREQUESTMAPPER, webAppControllerReader.getRequestMapper()); 50 | } 51 | } -------------------------------------------------------------------------------- /web-containerembed/src/main/java/com/tg/web/controller/AInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.controller; 2 | 3 | import com.tg.tiny4j.core.ioc.annotation.Inject; 4 | import com.tg.tiny4j.core.ioc.annotation.Value; 5 | import com.tg.tiny4j.web.annotation.Interceptor; 6 | import com.tg.tiny4j.web.interceptor.HandlerInterceptor; 7 | import com.tg.web.service.UserService; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | 12 | /** 13 | * Created by twogoods on 16/11/9. 14 | */ 15 | @Interceptor(pathPatterns = {"/base/user"},order = 2) 16 | public class AInterceptor implements HandlerInterceptor{ 17 | 18 | @Value("${user.name:test}") 19 | private String name; 20 | 21 | @Inject 22 | private UserService userService; 23 | 24 | @Override 25 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response) { 26 | System.out.println("********** A interceptor ********"); 27 | System.out.println(name); 28 | // userService.query(); 29 | System.out.println("********** A interceptor end ********"); 30 | return true; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /web-containerembed/src/main/java/com/tg/web/controller/BInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.controller; 2 | 3 | import com.tg.tiny4j.web.annotation.Interceptor; 4 | import com.tg.tiny4j.web.interceptor.HandlerInterceptor; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | 9 | /** 10 | * Created by twogoods on 16/11/9. 11 | */ 12 | @Interceptor(pathPatterns = {"/base"},excludePathPatterns = {"/base/index"},order = 1) 13 | public class BInterceptor implements HandlerInterceptor { 14 | @Override 15 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response) { 16 | System.out.println("do b interceptor"); 17 | return true; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /web-containerembed/src/main/java/com/tg/web/controller/BaseController.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.controller; 2 | 3 | import com.tg.tiny4j.web.annotation.ExceptionHandler; 4 | 5 | /** 6 | * Created by twogoods on 16/11/4. 7 | */ 8 | public class BaseController { 9 | @ExceptionHandler(Exception.class) 10 | public String handleException(){ 11 | return "error"; 12 | } 13 | 14 | @ExceptionHandler(TestException.class) 15 | public String handleExc(){ 16 | return "test error"; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /web-containerembed/src/main/java/com/tg/web/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.controller; 2 | 3 | import com.tg.tiny4j.commons.constants.HttpMethod; 4 | import com.tg.tiny4j.core.ioc.annotation.Inject; 5 | import com.tg.tiny4j.core.ioc.annotation.Value; 6 | import com.tg.tiny4j.web.annotation.*; 7 | import com.tg.web.model.User; 8 | import com.tg.web.service.UserService; 9 | 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | /** 14 | * Created by twogoods on 16/12/1. 15 | */ 16 | @Api("/base") 17 | public class TestController extends BaseController { 18 | 19 | @Value("${user.name:test}") 20 | private String name; 21 | 22 | @Inject 23 | private UserService userService; 24 | 25 | @RequestMapping 26 | public String index() { 27 | userService.query(); 28 | return name; 29 | } 30 | 31 | @RequestMapping(mapUrl = "/test/{id}", method = HttpMethod.GET) 32 | @CROS(origins = "www.baidu.com", methods = {HttpMethod.GET}, maxAge = "3600") 33 | public String patgTest(@PathVariable("id") String id) { 34 | return id; 35 | } 36 | 37 | @RequestMapping(mapUrl = "/test", method = HttpMethod.GET) 38 | @InterceptorSelect(include = {"aInterceptor"}, exclude = {"bInterceptor"}) 39 | public String interceptorTest() { 40 | return "haha"; 41 | } 42 | 43 | 44 | @RequestMapping(mapUrl = "/exception", method = HttpMethod.GET) 45 | public String exceptionTest() { 46 | int i = 1 / 0; 47 | return "haha"; 48 | } 49 | 50 | @RequestMapping(mapUrl = "/index") 51 | @CROS 52 | public String paramTest(@RequestParam("id") long id, @RequestParam("name") String name) { 53 | return name + "---" + id; 54 | } 55 | 56 | 57 | @RequestMapping(mapUrl = "/user") 58 | @InterceptorExclude(interceptors = {"bInterceptor"}) 59 | public Map modelTest(@RequestParam("name") String name, @RequestParam User user) { 60 | Map map = new HashMap<>(); 61 | map.put("name", name); 62 | map.put("user", user); 63 | return map; 64 | } 65 | 66 | @RequestMapping(mapUrl = "/json", method = HttpMethod.POST) 67 | public User modelJson(@RequestBody User user) { 68 | return user; 69 | } 70 | 71 | @RequestMapping(mapUrl = "/user/{id}", method = HttpMethod.PUT) 72 | @CROS 73 | public User insert(@PathVariable("id") long id, @RequestBody User user) { 74 | return user; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /web-containerembed/src/main/java/com/tg/web/controller/TestException.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.controller; 2 | 3 | /** 4 | * Created by twogoods on 16/12/1. 5 | */ 6 | public class TestException extends RuntimeException{ 7 | public TestException() { 8 | } 9 | 10 | public TestException(String message) { 11 | super(message); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /web-containerembed/src/main/java/com/tg/web/controller/TestServlet.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.controller; 2 | 3 | import javax.servlet.ServletException; 4 | import javax.servlet.annotation.WebServlet; 5 | import javax.servlet.http.HttpServlet; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | import java.io.IOException; 9 | 10 | /** 11 | * Created by twogoods on 16/12/6. 12 | */ 13 | @WebServlet(name = "test",urlPatterns = {"/test"}) 14 | public class TestServlet extends HttpServlet{ 15 | 16 | @Override 17 | protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 18 | 19 | System.out.println("get in ..."); 20 | resp.setStatus(200); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /web-containerembed/src/main/java/com/tg/web/dao/UserDao.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.dao; 2 | 3 | import com.tg.tiny4j.core.ioc.annotation.Component; 4 | 5 | /** 6 | * Created by twogoods on 16/11/1. 7 | */ 8 | @Component 9 | public class UserDao { 10 | 11 | public void query(){ 12 | System.out.println("execute sql...."); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /web-containerembed/src/main/java/com/tg/web/model/User.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.model; 2 | 3 | /** 4 | * Created by twogoods on 16/11/7. 5 | */ 6 | public class User { 7 | private String name; 8 | private int age; 9 | 10 | public String getName() { 11 | return name; 12 | } 13 | 14 | public void setName(String name) { 15 | this.name = name; 16 | } 17 | 18 | public int getAge() { 19 | return age; 20 | } 21 | 22 | public void setAge(int age) { 23 | this.age = age; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /web-containerembed/src/main/java/com/tg/web/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.service; 2 | 3 | import com.tg.tiny4j.core.ioc.annotation.Component; 4 | import com.tg.tiny4j.core.ioc.annotation.Inject; 5 | import com.tg.web.dao.UserDao; 6 | 7 | /** 8 | * Created by twogoods on 16/11/1. 9 | */ 10 | @Component 11 | public class UserService { 12 | 13 | @Inject 14 | private UserDao userDao; 15 | 16 | 17 | public void query(){ 18 | userDao.query(); 19 | } 20 | 21 | public void setUserDao(UserDao userDao) { 22 | this.userDao = userDao; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /web-containerembed/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | tiny4j.component-scan = com.tg.web 2 | tiny4j.server.contextPath = /twogoods 3 | tiny4j.server.port = 8080 -------------------------------------------------------------------------------- /web-containerembed/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /web-containerembed/src/test/java/com/tg/embed/JetttyTest.java: -------------------------------------------------------------------------------- 1 | package com.tg.embed; 2 | 3 | import com.tg.tiny4j.web.contextlistener.SingleRestLoaderListener; 4 | import com.tg.tiny4j.web.servlet.DispatcherServlet; 5 | import org.eclipse.jetty.server.Request; 6 | import org.eclipse.jetty.server.Server; 7 | import org.eclipse.jetty.server.handler.AbstractHandler; 8 | import org.eclipse.jetty.servlet.ServletContextHandler; 9 | import org.junit.Test; 10 | 11 | import javax.servlet.ServletException; 12 | import javax.servlet.http.HttpServlet; 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | import java.io.IOException; 16 | import java.io.PrintWriter; 17 | 18 | /** 19 | * Description: 20 | * 21 | * @author twogoods 22 | * @version 0.1 23 | * @since 2017-03-31 24 | */ 25 | public class JetttyTest { 26 | @Test 27 | public void test() throws Exception { 28 | //http://www.eclipse.org/jetty/documentation/9.4.x/embedding-jetty.html 29 | Server server = new Server(8080); 30 | ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); 31 | context.setContextPath("/twogoods"); 32 | context.addEventListener(new SingleRestLoaderListener()); 33 | context.addServlet(DispatcherServlet.class, "/*"); 34 | server.setHandler(context); 35 | server.start(); 36 | server.join(); 37 | } 38 | 39 | 40 | public static class HelloServlet extends HttpServlet { 41 | @Override 42 | public void init() throws ServletException { 43 | System.out.println("HelloServlet init..."); 44 | } 45 | 46 | @Override 47 | protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 48 | response.setContentType("text/html"); 49 | response.setStatus(HttpServletResponse.SC_OK); 50 | response.getWriter().println("

Hello from HelloServlet

"); 51 | } 52 | } 53 | 54 | public static class DefaultServlet extends HttpServlet { 55 | @Override 56 | protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 57 | response.setContentType("text/html"); 58 | response.setStatus(HttpServletResponse.SC_OK); 59 | response.getWriter().println("

default

"); 60 | } 61 | } 62 | 63 | public static class HelloHandler extends AbstractHandler { 64 | public void handle(String target, 65 | Request baseRequest, 66 | HttpServletRequest request, 67 | HttpServletResponse response) throws IOException, 68 | ServletException { 69 | response.setContentType("text/html; charset=utf-8"); 70 | response.setStatus(HttpServletResponse.SC_NOT_FOUND); 71 | PrintWriter out = response.getWriter(); 72 | out.println("

" + 404 + "

"); 73 | baseRequest.setHandled(true); 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /web-containerembed/src/test/java/com/tg/embed/TomcatTest.java: -------------------------------------------------------------------------------- 1 | package com.tg.embed; 2 | 3 | import org.apache.catalina.WebResourceRoot; 4 | import org.apache.catalina.core.StandardContext; 5 | import org.apache.catalina.startup.Tomcat; 6 | import org.apache.catalina.webresources.DirResourceSet; 7 | import org.apache.catalina.webresources.StandardRoot; 8 | 9 | import java.io.File; 10 | 11 | /** 12 | * Description: 13 | * 14 | * @author twogoods 15 | * @version 0.1 16 | * @since 2017-03-31 17 | */ 18 | public class TomcatTest { 19 | 20 | //http://blog.csdn.net/hengyunabc/article/details/50120001 21 | public static void test(String[] args) throws Exception { 22 | String webappDirLocation = "web-test/src/main/webapp/"; 23 | Tomcat tomcat = new Tomcat(); 24 | 25 | //The port that we should run on can be set into an environment variable 26 | //Look for that variable and default to 8080 if it isn't there. 27 | String webPort = System.getenv("PORT"); 28 | if (webPort == null || webPort.isEmpty()) { 29 | webPort = "8080"; 30 | } 31 | tomcat.setPort(Integer.valueOf(webPort)); 32 | StandardContext ctx = (StandardContext) tomcat.addWebapp("/", new File(webappDirLocation).getAbsolutePath()); 33 | System.out.println("configuring app with basedir: " + new File(webappDirLocation).getAbsolutePath()); 34 | 35 | // Declare an alternative location for your "WEB-INF/classes" dir 36 | // Servlet 3.0 annotation will work 37 | File additionWebInfClasses = new File("web-test/target/classes"); 38 | WebResourceRoot resources = new StandardRoot(ctx); 39 | resources.addPreResources(new DirResourceSet(resources, "/WEB-INF/classes", 40 | additionWebInfClasses.getAbsolutePath(), "/")); 41 | ctx.setResources(resources); 42 | 43 | tomcat.start(); 44 | tomcat.getServer().await(); 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /web-test/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | tiny4j 5 | com.twogoods.tiny4j 6 | 0.0.1 7 | 8 | 4.0.0 9 | web-test 10 | war 11 | web-test Maven Webapp 12 | http://maven.apache.org 13 | 14 | 15 | com.twogoods.tiny4j 16 | rest 17 | 0.0.1 18 | 19 | 20 | com.twogoods.tiny4j 21 | core 22 | 0.0.1 23 | 24 | 25 | 26 | org.eclipse.jetty 27 | jetty-server 28 | 9.4.2.v20170220 29 | 30 | 31 | org.eclipse.jetty 32 | jetty-webapp 33 | 9.4.2.v20170220 34 | 35 | 36 | 37 | org.apache.logging.log4j 38 | log4j-core 39 | 2.7 40 | 41 | 42 | org.apache.logging.log4j 43 | log4j-web 44 | 2.7 45 | 46 | 47 | org.apache.logging.log4j 48 | log4j-api 49 | 2.7 50 | 51 | 52 | org.apache.logging.log4j 53 | log4j-slf4j-impl 54 | 2.8 55 | 56 | 57 | org.apache.logging.log4j 58 | log4j-jcl 59 | 2.8 60 | 61 | 62 | junit 63 | junit 64 | 3.8.1 65 | test 66 | 67 | 68 | 69 | 70 | web-test 71 | 72 | 73 | -------------------------------------------------------------------------------- /web-test/src/main/java/com/tg/web/contextlistener/WebAppLoaderListener.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.contextlistener; 2 | 3 | import com.tg.tiny4j.commons.constants.WebApplicationEnvironment; 4 | import com.tg.tiny4j.commons.utils.Validate; 5 | import com.tg.tiny4j.core.ioc.beans.BeanDefinition; 6 | import com.tg.tiny4j.core.web.integration.ContextListener.AbstractWebContextListener; 7 | import com.tg.tiny4j.core.web.integration.HandleAnnotation; 8 | import com.tg.tiny4j.core.web.integration.HandleRegistry; 9 | import com.tg.tiny4j.core.web.integration.context.WebApplicationContext; 10 | import com.tg.tiny4j.web.integration.WebAppControllerReader; 11 | import com.tg.tiny4j.web.metadata.BaseInfo; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | 16 | import javax.servlet.ServletContextEvent; 17 | 18 | /** 19 | * Created by twogoods on 16/11/2. 20 | */ 21 | public class WebAppLoaderListener extends AbstractWebContextListener { 22 | private static final Logger log = LoggerFactory.getLogger(WebAppLoaderListener.class); 23 | 24 | private final WebAppControllerReader webAppControllerReader = new WebAppControllerReader(); 25 | 26 | @Override 27 | public void registerHandle(HandleRegistry registry) { 28 | HandleAnnotation handle = new HandleAnnotation() { 29 | @Override 30 | public BeanDefinition handle(Class clazz) throws Exception { 31 | BaseInfo baseInfo = webAppControllerReader.read(clazz); 32 | if (Validate.isEmpty(baseInfo)) { 33 | return null; 34 | } else { 35 | return new BeanDefinition(baseInfo.getName(), baseInfo.getClassName()); 36 | } 37 | } 38 | }; 39 | registry.addHandle(handle); 40 | } 41 | 42 | @Override 43 | public void requestMapInitialized(ServletContextEvent servletContextEvent, WebApplicationContext applicationContext) throws Exception { 44 | webAppControllerReader.initRequestMap(); 45 | webAppControllerReader.setInstances(applicationContext.getBeans(webAppControllerReader.getControllerName())); 46 | servletContextEvent.getServletContext().setAttribute(WebApplicationEnvironment.WEBREQUESTMAPPER, webAppControllerReader.getRequestMapper()); 47 | } 48 | } -------------------------------------------------------------------------------- /web-test/src/main/java/com/tg/web/controller/AInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.controller; 2 | 3 | import com.tg.tiny4j.core.ioc.annotation.Inject; 4 | import com.tg.tiny4j.core.ioc.annotation.Value; 5 | import com.tg.tiny4j.web.annotation.Interceptor; 6 | import com.tg.tiny4j.web.interceptor.HandlerInterceptor; 7 | import com.tg.web.service.UserService; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | 12 | /** 13 | * Created by twogoods on 16/11/9. 14 | */ 15 | @Interceptor(pathPatterns = {"/base/user"},order = 2) 16 | public class AInterceptor implements HandlerInterceptor{ 17 | 18 | @Value("${user.name:test}") 19 | private String name; 20 | 21 | @Inject 22 | private UserService userService; 23 | 24 | @Override 25 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response) { 26 | System.out.println("********** A interceptor ********"); 27 | System.out.println(name); 28 | // userService.query(); 29 | System.out.println("********** A interceptor end ********"); 30 | return true; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /web-test/src/main/java/com/tg/web/controller/BInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.controller; 2 | 3 | import com.tg.tiny4j.web.annotation.Interceptor; 4 | import com.tg.tiny4j.web.interceptor.HandlerInterceptor; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | 9 | /** 10 | * Created by twogoods on 16/11/9. 11 | */ 12 | @Interceptor(pathPatterns = {"/base"},excludePathPatterns = {"/base/index"},order = 1) 13 | public class BInterceptor implements HandlerInterceptor { 14 | @Override 15 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response) { 16 | System.out.println("do b interceptor"); 17 | return true; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /web-test/src/main/java/com/tg/web/controller/BaseController.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.controller; 2 | 3 | import com.tg.tiny4j.web.annotation.*; 4 | 5 | /** 6 | * Created by twogoods on 16/11/4. 7 | */ 8 | public class BaseController { 9 | @ExceptionHandler(Exception.class) 10 | public String handleException(){ 11 | return "error"; 12 | } 13 | 14 | @ExceptionHandler(TestException.class) 15 | public String handleExc(){ 16 | return "test error"; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /web-test/src/main/java/com/tg/web/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.controller; 2 | 3 | import com.tg.tiny4j.commons.constants.HttpMethod; 4 | import com.tg.tiny4j.core.ioc.annotation.Inject; 5 | import com.tg.tiny4j.core.ioc.annotation.Value; 6 | import com.tg.tiny4j.web.annotation.*; 7 | import com.tg.web.model.User; 8 | import com.tg.web.service.UserService; 9 | 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | /** 14 | * Created by twogoods on 16/12/1. 15 | */ 16 | @Api("/base") 17 | public class TestController extends BaseController { 18 | 19 | @Value("${user.name:test}") 20 | private String name; 21 | 22 | @Inject 23 | private UserService userService; 24 | 25 | @RequestMapping 26 | public String index() { 27 | userService.query(); 28 | return name; 29 | } 30 | 31 | @RequestMapping(mapUrl = "/test/{id}", method = HttpMethod.GET) 32 | @CROS(origins = "www.baidu.com", methods = {HttpMethod.GET}, maxAge = "3600") 33 | public String patgTest(@PathVariable("id") String id) { 34 | return id; 35 | } 36 | 37 | @RequestMapping(mapUrl = "/test", method = HttpMethod.GET) 38 | @InterceptorSelect(include = {"aInterceptor"}, exclude = {"bInterceptor"}) 39 | public String interceptorTest() { 40 | return "haha"; 41 | } 42 | 43 | 44 | @RequestMapping(mapUrl = "/exception", method = HttpMethod.GET) 45 | public String exceptionTest() { 46 | int i = 1 / 0; 47 | return "haha"; 48 | } 49 | 50 | @RequestMapping(mapUrl = "/index") 51 | @CROS 52 | public String paramTest(@RequestParam("id") long id, @RequestParam("name") String name) { 53 | return name + "---" + id; 54 | } 55 | 56 | 57 | @RequestMapping(mapUrl = "/user") 58 | @InterceptorExclude(interceptors = {"bInterceptor"}) 59 | public Map modelTest(@RequestParam("name") String name, @RequestParam User user) { 60 | Map map = new HashMap<>(); 61 | map.put("name", name); 62 | map.put("user", user); 63 | return map; 64 | } 65 | 66 | @RequestMapping(mapUrl = "/json", method = HttpMethod.POST) 67 | public User modelJson(@RequestBody User user) { 68 | return user; 69 | } 70 | 71 | @RequestMapping(mapUrl = "/user/{id}", method = HttpMethod.PUT) 72 | @CROS 73 | public User insert(@PathVariable("id") long id, @RequestBody User user) { 74 | return user; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /web-test/src/main/java/com/tg/web/controller/TestException.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.controller; 2 | 3 | /** 4 | * Created by twogoods on 16/12/1. 5 | */ 6 | public class TestException extends RuntimeException{ 7 | public TestException() { 8 | } 9 | 10 | public TestException(String message) { 11 | super(message); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /web-test/src/main/java/com/tg/web/controller/TestServlet.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.controller; 2 | 3 | import javax.servlet.ServletException; 4 | import javax.servlet.annotation.WebServlet; 5 | import javax.servlet.http.HttpServlet; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | import java.io.IOException; 9 | 10 | /** 11 | * Created by twogoods on 16/12/6. 12 | */ 13 | @WebServlet(name = "test",urlPatterns = {"/test"}) 14 | public class TestServlet extends HttpServlet{ 15 | 16 | @Override 17 | protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 18 | 19 | System.out.println("get in ..."); 20 | resp.setStatus(200); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /web-test/src/main/java/com/tg/web/dao/UserDao.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.dao; 2 | 3 | import com.tg.tiny4j.core.ioc.annotation.Component; 4 | 5 | /** 6 | * Created by twogoods on 16/11/1. 7 | */ 8 | @Component 9 | public class UserDao { 10 | 11 | public void query(){ 12 | System.out.println("execute sql...."); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /web-test/src/main/java/com/tg/web/model/User.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.model; 2 | 3 | /** 4 | * Created by twogoods on 16/11/7. 5 | */ 6 | public class User { 7 | private String name; 8 | private int age; 9 | 10 | public String getName() { 11 | return name; 12 | } 13 | 14 | public void setName(String name) { 15 | this.name = name; 16 | } 17 | 18 | public int getAge() { 19 | return age; 20 | } 21 | 22 | public void setAge(int age) { 23 | this.age = age; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /web-test/src/main/java/com/tg/web/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.tg.web.service; 2 | 3 | import com.tg.tiny4j.core.ioc.annotation.Component; 4 | import com.tg.tiny4j.core.ioc.annotation.Inject; 5 | import com.tg.web.dao.UserDao; 6 | 7 | /** 8 | * Created by twogoods on 16/11/1. 9 | */ 10 | @Component 11 | public class UserService { 12 | 13 | @Inject 14 | private UserDao userDao; 15 | 16 | 17 | public void query(){ 18 | userDao.query(); 19 | } 20 | 21 | public void setUserDao(UserDao userDao) { 22 | this.userDao = userDao; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /web-test/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | tiny4j.component-scan = com.tg.web 2 | tiny4j.server.contextPath = /admin 3 | tiny4j.server.port = 8088 4 | user.name=twogoods 5 | user.pass=twogoods -------------------------------------------------------------------------------- /web-test/src/main/resources/application.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | application.properties 5 | ${tiny4j.component-scan:com.tg.web.controller} 6 | 7 | -------------------------------------------------------------------------------- /web-test/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /web-test/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | Archetype Created Web Application 6 | 7 | 8 | component-scan 9 | com.tg.web 10 | 11 | 12 | 13 | com.tg.web.contextlistener.WebAppLoaderListener 14 | 15 | 16 | 17 | 18 | dispatcherServlet 19 | com.tg.tiny4j.web.servlet.DispatcherServlet 20 | 21 | 22 | 23 | dispatcherServlet 24 | / 25 | 26 | 27 | -------------------------------------------------------------------------------- /web-test/src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Hello World! twogoods

4 | 5 | 6 | --------------------------------------------------------------------------------