├── .gitignore ├── README.md ├── pom.xml ├── src ├── main │ ├── java │ │ └── com │ │ │ ├── brian │ │ │ ├── MainTest.java │ │ │ ├── aop │ │ │ │ ├── LogAspects.java │ │ │ │ └── MathCalculator.java │ │ │ ├── async │ │ │ │ ├── Callable01.java │ │ │ │ ├── DeferredResult02.java │ │ │ │ └── ResultQueue.java │ │ │ ├── bean │ │ │ │ ├── Alan.java │ │ │ │ ├── Brian.java │ │ │ │ ├── BrianBeanFactory.java │ │ │ │ ├── Person.java │ │ │ │ ├── Vincent.java │ │ │ │ └── WenTao.java │ │ │ ├── condition │ │ │ │ ├── BrianCondition.java │ │ │ │ └── BrianSelector.java │ │ │ ├── config │ │ │ │ ├── BrianTypeFilter.java │ │ │ │ ├── MainConfig.java │ │ │ │ ├── MainConfigOfAOP.java │ │ │ │ ├── MainConfigOfAutowired.java │ │ │ │ ├── MainConfigOfLifeCycle.java │ │ │ │ ├── MainConfigOfProfile.java │ │ │ │ └── MainConfigOfPropertyValues.java │ │ │ ├── controller │ │ │ │ └── BookController.java │ │ │ ├── ext │ │ │ │ ├── BrianApplicationListener.java │ │ │ │ ├── BrianBeanDefinitionRegistryPostProcessor.java │ │ │ │ ├── BrianBeanFactoryPostProcessor.java │ │ │ │ ├── BrianService.java │ │ │ │ └── ExtConfig.java │ │ │ ├── mvc │ │ │ │ ├── BrianWebAppInitializer.java │ │ │ │ ├── config │ │ │ │ │ ├── AppConfig.java │ │ │ │ │ └── WebConfig.java │ │ │ │ ├── controller │ │ │ │ │ └── TestController.java │ │ │ │ └── service │ │ │ │ │ └── TestService.java │ │ │ ├── repository │ │ │ │ └── BookRepository.java │ │ │ ├── service │ │ │ │ ├── BookService.java │ │ │ │ └── impl │ │ │ │ │ ├── BookServiceImpl.java │ │ │ │ │ └── OtherBookServiceImpl.java │ │ │ └── tx │ │ │ │ ├── AccessRightService.java │ │ │ │ ├── AccessRigntDao.java │ │ │ │ └── TxConfig.java │ │ │ └── write │ │ │ ├── annotation │ │ │ ├── BrianAnnotation.java │ │ │ ├── TestGetAnnotation.java │ │ │ └── transaction │ │ │ │ ├── BrianTransaction.java │ │ │ │ ├── TransactionUtils.java │ │ │ │ ├── aop │ │ │ │ └── BrianAopTransaction.java │ │ │ │ ├── config │ │ │ │ └── Config.java │ │ │ │ ├── dao │ │ │ │ └── TJsonDao.java │ │ │ │ └── service │ │ │ │ └── TJsonService.java │ │ │ ├── bjdbc │ │ │ ├── BrianDbPool.java │ │ │ ├── BrianDbPoolImpl.java │ │ │ └── DbBean.java │ │ │ ├── blinklist │ │ │ └── BrianLinkList.java │ │ │ ├── blist │ │ │ ├── BrianArrayList.java │ │ │ └── BrianList.java │ │ │ ├── bmap │ │ │ ├── BrianHashMap.java │ │ │ └── BrianMap.java │ │ │ ├── bmvc │ │ │ ├── annotation │ │ │ │ ├── BrianController.java │ │ │ │ └── BrianRequestMapping.java │ │ │ ├── controller │ │ │ │ └── TestController.java │ │ │ └── servlet │ │ │ │ └── BrianDispatcherServlet.java │ │ │ ├── bmybatis │ │ │ ├── domain │ │ │ │ └── TJson.java │ │ │ ├── mapper │ │ │ │ └── TJsonMapper.java │ │ │ ├── orm │ │ │ │ ├── annotaton │ │ │ │ │ ├── BrianInsert.java │ │ │ │ │ ├── BrianParam.java │ │ │ │ │ └── BrianSelect.java │ │ │ │ └── aop │ │ │ │ │ └── BrianInvocationHandler.java │ │ │ ├── sql │ │ │ │ └── SqlSession.java │ │ │ └── utils │ │ │ │ ├── JDBCUtils.java │ │ │ │ └── SQLUtils.java │ │ │ └── bservice │ │ │ ├── BrianAnnotationConfigApplicationContext.java │ │ │ └── annotation │ │ │ ├── BrianResource.java │ │ │ ├── BrianService.java │ │ │ ├── service │ │ │ ├── BaseService.java │ │ │ └── OtherService.java │ │ │ └── utils │ │ │ └── ClassUtil.java │ ├── resources │ │ ├── SpringSources.txt │ │ ├── app.properties │ │ └── app.yml │ └── webapp │ │ └── WEB-INF │ │ └── web.xml └── test │ └── java │ ├── BASEIC_LIST_TEST.java │ ├── BASEIC_MAP_TEST.java │ ├── IOC_TEST_AOP.java │ ├── IOC_TEST_Autowired.java │ ├── IOC_TEST_EXT.java │ ├── IOC_TEST_PropertyValues.java │ ├── IOC_TEST_TX.java │ ├── IOC_test_Profile.java │ ├── JDBC_TEST_CONNECT.java │ ├── MYBATIS_TEST_ORM.java │ └── MianTest.java └── target ├── classes ├── SpringSources.txt ├── app.properties └── app.yml └── maven-status └── maven-compiler-plugin └── compile └── default-compile ├── createdFiles.lst └── inputFiles.lst /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | /target/ 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 天道酬请,一步一个坑 2 | ### spring-annotation 3 | 4 | #### 1.源码分析 5 | ##### 1.1 Spring 5.X 源码分析 6 | ###### 1.1.1 Spring5源码深度解析(一)之理解Configuration注解 https://www.cnblogs.com/hlkawa/p/11085020.html 7 | ###### 1.1.2 Spring5源码深度分析(二)之理解@Conditional,@Import注解 https://www.cnblogs.com/hlkawa/p/11088129.html 8 | ###### 1.1.3 Spring5深度源码分析(三)之AnnotationConfigApplicationContext启动原理分析 https://www.cnblogs.com/hlkawa/p/11100604.html 9 | 10 | #### 2. 手写框架 11 | ##### 2.1手写 Spring事务框架 12 | ##### 2.2 手写@Service和@Resource注解 13 | ##### 2.3 手写SpringMVC框架(手写SpringMVC控制框,手写@Controller注解,手写@RequestMapping注解) 14 | ##### 2.4手写数据库连接池 15 | ##### 2.5 手写orm框架--mybatis 16 | ##### 2.6 手写ArrayList集合 17 | ##### 2.7 手写LinkList集合 18 | ##### 2.8 手写HashMap结合(数组+单向链表实现) 19 | 20 | #### 3. 项目重构或项目设计时常用的设计模式 https://gitee.com/showkawa_admin/architect/tree/master/designPattern 21 | ##### 3.1 策略模式 strategy 22 | ##### 3.2 责任链模式 responsibilitychain 23 | ##### 3.3 模板方法模式 template 24 | ##### 3.4 装饰器模式 decorative 25 | ##### 3.5 代理模式 proxy 26 | ##### 3.6 观察者模式 observer 27 | ##### 3.7 单例模式 singleton 28 | ##### 3.8 适配器模式 adapter 29 | 30 | #### 4.微服务SpringCloud2.X https://gitee.com/showkawa_admin/architect/tree/master/microservice 31 | ##### 4.1 服务治理 eureka 32 | ##### 4.2 DiscoveryClient实现负载均衡,轮询模式 33 | ##### 4.3 feign客户端调用,给人感觉就像调用本地服务一样 34 | ##### 4.4 config分布式配置中心 35 | ##### 4.5 apollo分布式配置中心 36 | ##### 4.6 zuul动态网关和统一API管理 37 | ##### 4.7 config分布式配置中心 + bus消息总线实现全局微服务的通知 38 | ##### 4.8 zipkin链路追踪 主要是微服务复杂调用的时候方便第一时间快速定位问题 39 | 40 | #### 5.互联网高并发场景 https://gitee.com/showkawa_admin/architect/tree/master/concurrent 41 | ##### 5.1 服务保护断路器 hystrix 42 | ##### 5.2 服务限流 ratelimit 43 | ##### 5.3 rabbitMQ 消息幂等性设计和分布式事务处理 rabbitmq 44 | ##### 5.4 lcn 分布式事务 45 | ##### 5.5 sharding-jdbc 分库分表 46 | 47 | #### 6.互联网安全架构 https://gitee.com/showkawa_admin/architect/tree/master/security 48 | ##### 6.1 预防xss跨站脚本攻击 xss 49 | ##### 6.2 防盗链技术 doorchain 50 | ##### 6.3 接口幂等性设计 idempotent 51 | ##### 6.3 springboot security细粒度基于页面的权限控制 52 | 53 | #### 7 lambda 表达式 54 | ##### 7.1 lambda https://gitee.com/showkawa_admin/netty-annotation/tree/master/src/main/java/com/brian/java8/lambda 55 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | brian.annotation 8 | com.annotation 9 | 1.0.1 10 | 11 | 12 | 17 13 | 17 14 | 17 15 | 16 | 17 | 18 | 19 | 20 | org.springframework 21 | spring-context 22 | 5.3.18 23 | 24 | 25 | org.springframework 26 | spring-aspects 27 | 5.3.18 28 | 29 | 30 | org.springframework 31 | spring-jdbc 32 | 5.3.18 33 | 34 | 35 | 36 | 37 | javax.servlet 38 | javax.servlet-api 39 | 4.0.1 40 | provided 41 | 42 | 43 | org.springframework 44 | spring-webmvc 45 | 5.3.18 46 | 47 | 48 | 49 | 50 | junit 51 | junit 52 | 4.13.1 53 | test 54 | 55 | 56 | 57 | 58 | c3p0 59 | c3p0 60 | 0.9.1.2 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | org.apache.maven.plugins 78 | maven-compiler-plugin 79 | 80 | 17 81 | 17 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/main/java/com/brian/MainTest.java: -------------------------------------------------------------------------------- 1 | package com.brian; 2 | 3 | import com.brian.config.MainConfig; 4 | import com.brian.controller.BookController; 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 7 | 8 | import java.lang.reflect.InvocationTargetException; 9 | import java.lang.reflect.Method; 10 | 11 | public class MainTest { 12 | public static void main(String[] args) { 13 | ApplicationContext mainConfig = 14 | new AnnotationConfigApplicationContext(MainConfig.class); 15 | 16 | System.out.println("MainConfig容器创建成功"); 17 | 18 | BookController bookController = mainConfig.getBean(BookController.class); 19 | try { 20 | Method printBook = bookController.getClass().getDeclaredMethod("printBook"); 21 | printBook.setAccessible(true); 22 | printBook.invoke(bookController); 23 | } catch (NoSuchMethodException e) { 24 | e.printStackTrace(); 25 | } catch (IllegalAccessException e) { 26 | e.printStackTrace(); 27 | } catch (InvocationTargetException e) { 28 | e.printStackTrace(); 29 | } 30 | // Alan alan1 = acac.getBean(Alan.class); 31 | // System.out.println("--ALAN--:" + alan1); 32 | // Alan alan2 = acac.getBean(Alan.class); 33 | //System.out.println("比较两个Alan实例: " + (alan1 == alan2)); 34 | 35 | // Person person1 = (Person) acac.getBean("person01"); 36 | // System.out.println("---main---test---person1---: " + person1.toString()); 37 | // Person person2 = (Person) acac.getBean("person02"); 38 | // System.out.println("---main---test---person2---: " + person2.toString()); 39 | 40 | 41 | // MathCalculator mathCalculator = (MathCalculator) acac.getBean("mathCalculator"); 42 | // System.out.println("----get--mathCalculator---: " + mathCalculator); 43 | 44 | // BrianBeanFactory beanFactory = acac.getBean(BrianBeanFactory.class); 45 | // WenTao wentao = null; 46 | // try { 47 | // wentao = beanFactory.getObject(); 48 | // } catch (Exception e) { 49 | // e.printStackTrace(); 50 | // } 51 | // System.out.println("----get--WenTao---: " + wentao); 52 | 53 | 54 | //关闭ioc容器 55 | ((AnnotationConfigApplicationContext) mainConfig).close(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/brian/aop/LogAspects.java: -------------------------------------------------------------------------------- 1 | package com.brian.aop; 2 | 3 | 4 | import org.aspectj.lang.JoinPoint; 5 | import org.aspectj.lang.annotation.*; 6 | 7 | import java.lang.reflect.Array; 8 | import java.util.Arrays; 9 | 10 | @Aspect 11 | public class LogAspects { 12 | 13 | @Pointcut("execution(public int com.brian.aop.MathCalculator.*(..))") 14 | public void pointCut() { } 15 | 16 | @Before("com.brian.aop.LogAspects.pointCut()") 17 | public void logStart(JoinPoint joinPoint) { 18 | String methodName = joinPoint.getSignature().getName(); 19 | Object[] per = joinPoint.getArgs(); 20 | System.out.println( methodName+"()...@Before... 入参:{"+ Arrays.asList(per) +"}"); 21 | } 22 | @After("com.brian.aop.LogAspects.pointCut()") 23 | public void logEnd(JoinPoint joinPoint) { 24 | String methodName = joinPoint.getSignature().getName(); 25 | System.out.println(methodName+"()... @After..."); 26 | } 27 | @AfterReturning(value = "com.brian.aop.LogAspects.pointCut()",returning = "re") 28 | public void logReturn(Object re) { 29 | System.out.println("@AfterReturning... 返回值:{"+ re +"}"); 30 | } 31 | @AfterThrowing(value = "com.brian.aop.LogAspects.pointCut()",throwing = "ex") 32 | public void logThrowing(Exception ex) { 33 | System.out.println("@AfterThrowing... 异常信息:{"+ ex+"}"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/brian/aop/MathCalculator.java: -------------------------------------------------------------------------------- 1 | package com.brian.aop; 2 | 3 | public class MathCalculator { 4 | 5 | public int div( int i,int j) { 6 | System.out.println("MathCalculator.div() method excute..."); 7 | return i/j; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/brian/async/Callable01.java: -------------------------------------------------------------------------------- 1 | package com.brian.async; 2 | 3 | 4 | import org.springframework.stereotype.Controller; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.ResponseBody; 7 | 8 | import java.util.concurrent.Callable; 9 | 10 | /** 11 | * SpringMVC异步调用 Callable =>执行过程 12 | * 1.控制器返回Callable 13 | * 2.Spring异步调用,将Callable提交到TaskExecutor使用一个隔离的线程进行执行 14 | * 3.DispatcherServlet和所有的Filter退出web容器的线程,而response保持打开的状态 15 | * 4.Callable返回结果,SpringMVC将请求重新派发给容器,并且恢复之前的处理。 16 | * 5.根据Callable返回的结果。SpringMVC继续进行试图渲染流程等等等等。 17 | */ 18 | @Controller 19 | public class Callable01 { 20 | 21 | @ResponseBody 22 | @RequestMapping("/async01") 23 | public Callable async01() { 24 | 25 | System.out.println("主线程start...." + Thread.currentThread()+"-"+System.currentTimeMillis()); 26 | Callable callable = new Callable() { 27 | 28 | public String call() throws Exception { 29 | System.out.println("callable线程start...." + Thread.currentThread() + "-" + System.currentTimeMillis()); 30 | Thread.sleep(3000); 31 | System.out.println("callable线程end...." + Thread.currentThread() + "-" + System.currentTimeMillis()); 32 | return "ok"; 33 | } 34 | }; 35 | System.out.println("主线程end...." + Thread.currentThread()+"-"+System.currentTimeMillis()); 36 | return callable; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/brian/async/DeferredResult02.java: -------------------------------------------------------------------------------- 1 | package com.brian.async; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.context.request.async.DeferredResult; 6 | 7 | import java.util.UUID; 8 | 9 | /** 10 | * DeferredResult异步调用 11 | * 12 | */ 13 | @Controller 14 | public class DeferredResult02 { 15 | 16 | @RequestMapping("/create") 17 | public DeferredResult createOrder() { 18 | DeferredResult deferredResult = 19 | new DeferredResult((long)15000,"create order fail"); 20 | //存放到模拟的队列中 21 | ResultQueue.add(deferredResult); 22 | return deferredResult; 23 | } 24 | 25 | 26 | @RequestMapping("/create/action") 27 | public String createAction() { 28 | DeferredResult deferredResult = ResultQueue.get(); 29 | String order = UUID.randomUUID().toString(); 30 | deferredResult.setResult(order); 31 | return " create order id: " + order; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/brian/async/ResultQueue.java: -------------------------------------------------------------------------------- 1 | package com.brian.async; 2 | 3 | import org.springframework.web.context.request.async.DeferredResult; 4 | 5 | import java.util.Queue; 6 | import java.util.concurrent.ConcurrentLinkedDeque; 7 | 8 | /** 9 | * 模拟一个队列 10 | */ 11 | public class ResultQueue { 12 | 13 | private static Queue> queue = 14 | new ConcurrentLinkedDeque>(); 15 | 16 | public static void add(DeferredResult deferredResult){ 17 | queue.add(deferredResult); 18 | } 19 | 20 | public static DeferredResult get(){ 21 | return queue.poll(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/brian/bean/Alan.java: -------------------------------------------------------------------------------- 1 | package com.brian.bean; 2 | 3 | public class Alan { 4 | public Alan() { 5 | System.out.println("Alan constructor..."); 6 | } 7 | 8 | public void init() { 9 | System.out.println("Alan ... init..."); 10 | } 11 | 12 | public void destroy() { 13 | System.out.println("Alan... destroy..."); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/brian/bean/Brian.java: -------------------------------------------------------------------------------- 1 | package com.brian.bean; 2 | 3 | import org.springframework.beans.factory.DisposableBean; 4 | import org.springframework.beans.factory.InitializingBean; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.context.annotation.PropertySource; 8 | import org.springframework.stereotype.Component; 9 | 10 | //@Component 11 | @PropertySource(value = {"classpath:/app.properties"}) 12 | public class Brian implements InitializingBean , DisposableBean { 13 | 14 | private WenTao wenTao; 15 | 16 | @Value("${database02.name}") 17 | private String printAttr; 18 | 19 | public String getPrintAttr() { 20 | return printAttr; 21 | } 22 | 23 | public void setPrintAttr(String printAttr) { 24 | this.printAttr = printAttr; 25 | } 26 | 27 | public Brian(WenTao wenTao) { 28 | this.wenTao = wenTao; 29 | System.out.println("Brian... 有参构造器..."); 30 | } 31 | 32 | public WenTao getWenTao() { 33 | return wenTao; 34 | } 35 | 36 | // @Autowired 37 | public void setWenTao(WenTao wenTao) { 38 | this.wenTao = wenTao; 39 | } 40 | 41 | public void destroy() throws Exception { 42 | System.out.println("Brian... destroy..."); 43 | System.out.println(this.printAttr); 44 | } 45 | 46 | public void afterPropertiesSet() throws Exception { 47 | System.out.println("Brian... init..."); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/brian/bean/BrianBeanFactory.java: -------------------------------------------------------------------------------- 1 | package com.brian.bean; 2 | 3 | import org.springframework.beans.factory.FactoryBean; 4 | 5 | 6 | public class BrianBeanFactory implements FactoryBean { 7 | //获取对象 8 | public WenTao getObject() throws Exception { 9 | return new WenTao(); 10 | } 11 | //获取对象的类型 12 | public Class getObjectType() { 13 | return WenTao.class; 14 | } 15 | 16 | //获取对象是单例模式还是原型模式 17 | public boolean isSingleton() { 18 | return true; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/brian/bean/Person.java: -------------------------------------------------------------------------------- 1 | package com.brian.bean; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | 5 | public class Person { 6 | 7 | @Value("Tony") 8 | private String name; 9 | //@Value("19") 10 | private Integer age; 11 | @Value("${database.name}") 12 | private String attr; 13 | 14 | public String getName() { 15 | return name; 16 | } 17 | 18 | public void setName(String name) { 19 | this.name = name; 20 | } 21 | 22 | public Integer getAge() { 23 | return age; 24 | } 25 | 26 | public void setAge(Integer age) { 27 | this.age = age; 28 | } 29 | 30 | public String getAttr() { 31 | return attr; 32 | } 33 | 34 | public void setAttr(String attr) { 35 | this.attr = attr; 36 | } 37 | 38 | public Person() { 39 | } 40 | 41 | public Person(String name, Integer age) { 42 | this.name = name; 43 | this.age = age; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return "Person{" + 49 | "name='" + name + '\'' + 50 | ", age=" + age + 51 | ", attr='" + attr + '\'' + 52 | '}'; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/brian/bean/Vincent.java: -------------------------------------------------------------------------------- 1 | package com.brian.bean; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.config.BeanPostProcessor; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class Vincent implements BeanPostProcessor { 9 | 10 | /** 11 | * 12 | * @param o 13 | * @param s bean初始化增强 14 | * @return 15 | * @throws BeansException 16 | */ 17 | 18 | 19 | public Object postProcessBeforeInitialization(Object o, String s) throws BeansException { 20 | 21 | System.out.println("---postProcessBeforeInitialization:"+s); 22 | return new Vincent(); 23 | } 24 | 25 | public Object postProcessAfterInitialization(Object o, String s) throws BeansException { 26 | System.out.println("---postProcessAfterInitialization:"+s); 27 | return new Vincent(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/brian/bean/WenTao.java: -------------------------------------------------------------------------------- 1 | package com.brian.bean; 2 | 3 | 4 | import org.springframework.stereotype.Component; 5 | 6 | import javax.annotation.PostConstruct; 7 | import javax.annotation.PreDestroy; 8 | 9 | @Component 10 | public class WenTao { 11 | public WenTao() { 12 | System.out.println("wenTao... constructor..."); 13 | } 14 | //bean初始化并赋值后执行 15 | @PostConstruct 16 | public void init () { 17 | System.out.println("wenTao... init..."); 18 | } 19 | 20 | @PreDestroy 21 | public void destroy() { 22 | System.out.println("wenTao... destroy..."); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/brian/condition/BrianCondition.java: -------------------------------------------------------------------------------- 1 | package com.brian.condition; 2 | 3 | import org.springframework.context.annotation.Condition; 4 | import org.springframework.context.annotation.ConditionContext; 5 | import org.springframework.core.type.AnnotatedTypeMetadata; 6 | 7 | import java.util.Iterator; 8 | import java.util.List; 9 | 10 | public class BrianCondition implements Condition { 11 | 12 | /* 13 | * context:判断条件能使用的上下文(环境) 14 | * metadata: 注释信息 15 | * */ 16 | public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { 17 | 18 | System.out.println("---male:" + context.getRegistry().containsBeanDefinition("person")); 19 | if(context.getRegistry().containsBeanDefinition("person")) 20 | return false; 21 | 22 | return false; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/brian/condition/BrianSelector.java: -------------------------------------------------------------------------------- 1 | package com.brian.condition; 2 | 3 | import com.brian.config.MainConfigOfAOP; 4 | import org.springframework.context.annotation.ImportSelector; 5 | import org.springframework.core.type.AnnotationMetadata; 6 | 7 | /* 8 | * 自定义返回需要导入的组件 9 | * */ 10 | public class BrianSelector implements ImportSelector { 11 | 12 | /** 13 | * 14 | * @param importingClassMetadata 当前被标记有@Import注解的所有注解信息 15 | * @return 16 | */ 17 | public String[] selectImports(AnnotationMetadata importingClassMetadata) { 18 | 19 | System.out.println("----当前配置类----:"+importingClassMetadata.getClassName()); 20 | return new String[]{}; 21 | //return new String[]{MainConfigOfAOP.class.getName()}; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/brian/config/BrianTypeFilter.java: -------------------------------------------------------------------------------- 1 | package com.brian.config; 2 | 3 | import org.springframework.core.type.classreading.MetadataReader; 4 | import org.springframework.core.type.classreading.MetadataReaderFactory; 5 | import org.springframework.core.type.filter.TypeFilter; 6 | 7 | import java.io.IOException; 8 | 9 | public class BrianTypeFilter implements TypeFilter { 10 | /* 11 | * 12 | * metadataReader:读取到的当前正在扫描类的信息 13 | * metadataReaderFactory: 可以获取到其他类的任何信息 14 | * */ 15 | public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { 16 | System.out.println("getClassMetadata--:" + metadataReader.getClassMetadata().getClassName()); 17 | if(metadataReader.getClassMetadata().getClassName().contains("BrianBeanFactory")) 18 | { 19 | return true; 20 | } 21 | return false; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/brian/config/MainConfig.java: -------------------------------------------------------------------------------- 1 | package com.brian.config; 2 | 3 | import com.brian.bean.Alan; 4 | import com.brian.bean.Brian; 5 | import com.brian.bean.BrianBeanFactory; 6 | import com.brian.bean.Person; 7 | import com.brian.condition.BrianCondition; 8 | import com.brian.condition.BrianSelector; 9 | import com.brian.service.BookService; 10 | import org.springframework.context.annotation.*; 11 | import org.springframework.stereotype.Controller; 12 | 13 | @Configuration //告诉spring这是一个配置类 14 | /* 15 | * @ComponentScan 16 | * value:只当于扫描的的包 17 | * excludeFilters = 指定扫描的时候按照什么规则排除哪些组件 18 | * includeFilters = 指定扫描的时候只需要包含哪些组件 19 | * Filter.ANNOTATION:按照注解 20 | * Filter.ASSIGNABLE_TYPE: 按照给定的类型 21 | * */ 22 | 23 | //@ComponentScans(value = { 24 | // @ComponentScan(value = "com.brian",includeFilters = { 25 | // @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}), 26 | // @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,classes = {BookService.class}), 27 | // @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {BrianTypeFilter.class}) 28 | // },useDefaultFilters = false) 29 | //}) 30 | @ComponentScan({"com.brian.service", "com.brian.controller"}) 31 | //@Import({Brian.class,Alan.class}) 32 | @Import({BrianSelector.class}) 33 | public class MainConfig { 34 | 35 | @Bean("person") //给容器中注册一个Bean;类型为返回值的类型;id默认是方法名作为id 36 | public Person person(){ 37 | return new Person("Alan",18); 38 | } 39 | 40 | 41 | /* 42 | * @Conditional() 按照条件注册 43 | * 44 | * */ 45 | @Conditional({BrianCondition.class}) 46 | @Bean("person01") 47 | public Person person01() { 48 | return new Person("Brian",17); 49 | } 50 | 51 | @Conditional({BrianCondition.class}) 52 | @Bean("person02") 53 | public Person person02() { 54 | return new Person("wenTao",19); 55 | } 56 | 57 | /* 58 | * 59 | *给容器中注册组件 60 | * 1,包扫描+ 组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的方法] 61 | * 2, @Bean [导入的第三方包里面的组件] 62 | * 3,@Import [快速的给容器导入一个组件] 63 | * 1.@Import(要导入的组件class) 64 | * 2.ImportSelector:返回需要导入的组件的全类名数组 65 | * 3.ImportBeanDefinitionRegistrar: 手动注册bean到容器 66 | * 4. 使用Spring提供的FactoryBean 67 | * */ 68 | @Bean 69 | public BrianBeanFactory brianBeanFactory() { 70 | return new BrianBeanFactory(); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/brian/config/MainConfigOfAOP.java: -------------------------------------------------------------------------------- 1 | package com.brian.config; 2 | 3 | 4 | import com.brian.aop.LogAspects; 5 | import com.brian.aop.MathCalculator; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.context.annotation.EnableAspectJAutoProxy; 9 | import org.springframework.scheduling.annotation.EnableAsync; 10 | 11 | /** 12 | * AOP: [动态代理] 13 | * 指在程序运行时期间将某段代码切入到指定方法指定位置执行的编程方式 14 | * 15 | * 1.将业务逻辑类和切面类注入到容器中(加上@Aspect注解表示切面类 ) 16 | * 2.在切面类上的每个通知方法注解上注解,定义好切点 17 | * 3.开启基于注解的AOP模式: @EnableAspectAutoProxy 18 | * 19 | * 20 | * AOP 原理: 21 | * @EnableAspectJAutoProxy 22 | * @Import(AspectJAutoProxyRegistrar.class) 给容器中导入AspectJAutoProxyRegistrar类 23 | * 利用AspectJAutoProxyRegistrar自定义向容器中注册bean 24 | * AnnotationAwareAspectJAutoProxyCreator 25 | * ->AspectJAwareAdvisorAutoProxyCreator 26 | * ->AbstractAdvisorAutoProxyCreator 27 | * ->AbstractAutoProxyCreator 28 | * implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware 29 | * 后置处理器(在bean初始化完成前后执行) ,自动装配BeanFactory 30 | * 31 | * 32 | * 33 | */ 34 | @Configuration 35 | @EnableAspectJAutoProxy 36 | public class MainConfigOfAOP { 37 | 38 | @Bean 39 | public MathCalculator mathCalculator() 40 | { 41 | return new MathCalculator(); 42 | } 43 | 44 | @Bean 45 | public LogAspects logAspects() { 46 | return new LogAspects(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/brian/config/MainConfigOfAutowired.java: -------------------------------------------------------------------------------- 1 | package com.brian.config; 2 | 3 | 4 | import com.mchange.v2.c3p0.ComboPooledDataSource; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.ComponentScan; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.context.annotation.EnableAspectJAutoProxy; 9 | import org.springframework.jdbc.core.JdbcTemplate; 10 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 11 | import org.springframework.transaction.annotation.EnableTransactionManagement; 12 | 13 | import javax.sql.DataSource; 14 | import java.beans.PropertyVetoException; 15 | 16 | /** 17 | * 自动装配 18 | * Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值 19 | *1).@Autowired,自动注入: 20 | * 1.默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class); 21 | * 2.如果找到多个相同类型的组件,再将属性方法的名称作为组件的id去容器中查找 22 | * applicationContext.getBean("bookDao"); 23 | * 3.@Qualifier("bookDao"):使用@Qualifier指定需要装配的组件id,而不是使用属性名 24 | * 4.自动装配默认一定要将属性赋值好,没有就会报错 25 | * 使用@Autoeired(required=false),没有默认值也不会报错 26 | * 5.@Primary, 让Spring进行自动装配的时候,默认使用首先的Bean 27 | * 28 | * 2).Spring还支持使用@Resource(JSR250)和@Inject(JSR330) [java规范的注解] 29 | * 3).@Autowired :构造器,参数,方法,属性, 30 | * 31 | */ 32 | @EnableAspectJAutoProxy //开启AOP代理自动配置 33 | @EnableTransactionManagement //基于注解的事务管理 34 | //@ComponentScan(value = {"com.brian.bean","com.write.annotation"}) 35 | @ComponentScan(value = {"com.write.annotation.transaction"}) 36 | @Configuration 37 | public class MainConfigOfAutowired { 38 | 39 | @Bean 40 | public DataSource dataSource() throws PropertyVetoException { 41 | ComboPooledDataSource dataSource = new ComboPooledDataSource(); 42 | dataSource.setJdbcUrl("jdbc:mysql://remotemysql.com:3306/khgvUiO4eh"); 43 | dataSource.setUser("khgvUiO4eh"); 44 | dataSource.setPassword("BGAAee478r"); 45 | dataSource.setDriverClass("com.mysql.jdbc.Driver"); 46 | return dataSource; 47 | } 48 | 49 | @Bean 50 | public DataSourceTransactionManager platformTransactionManager() throws PropertyVetoException { 51 | return new DataSourceTransactionManager(this.dataSource()); 52 | } 53 | 54 | @Bean 55 | public JdbcTemplate jdbcTemplate () throws PropertyVetoException { 56 | return new JdbcTemplate(this.dataSource()); 57 | } 58 | 59 | 60 | 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/brian/config/MainConfigOfLifeCycle.java: -------------------------------------------------------------------------------- 1 | package com.brian.config; 2 | 3 | import com.brian.bean.Alan; 4 | import com.brian.bean.Vincent; 5 | import org.springframework.context.annotation.*; 6 | 7 | /** 8 | * bean的生命周期: 9 | * bean创建---初始化---销毁的过程 10 | * 11 | * 自定义初始化和销毁的方法 12 | * 13 | * 构造(对象创建) 14 | * 单实例:在容器启动时创建对象 15 | * 多实例:在每次获取的时候创建对象 16 | * 初始化: 17 | * 对象创建完成,并赋值,调用初始化方法 18 | * 销毁: 19 | * 单实例:ioc容器关闭时销毁 20 | * 多实例: 21 | * 1).指定初始化和销毁的方法: 22 | * 指定init-method和destroy-method 23 | * 2).通过让Bean实现 Spring InitializingBean(定义初始化逻辑) DisposableBean(定义销毁逻辑) 24 | * 3).可以使用JSR250: 25 | * @PostConstruct 在bean初始化并赋值后执行 26 | * @Predestroy 在bean销毁时执行 27 | * 4).BeanPostProcessor: bean的后置处理器 28 | * postProcessBeforeInitialization: 29 | * postProcessAfterInitialization 30 | */ 31 | @Configuration 32 | @ComponentScan("com.brian.bean") 33 | public class MainConfigOfLifeCycle { 34 | //@Scope("prototype") 35 | @Lazy 36 | @Bean(initMethod = "init", destroyMethod = "destroy") 37 | public Alan getAlan () { 38 | return new Alan(); 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/brian/config/MainConfigOfProfile.java: -------------------------------------------------------------------------------- 1 | package com.brian.config; 2 | 3 | import com.mchange.v2.c3p0.ComboPooledDataSource; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.context.EmbeddedValueResolverAware; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.context.annotation.Profile; 9 | import org.springframework.context.annotation.PropertySource; 10 | import org.springframework.util.StringValueResolver; 11 | 12 | import javax.sql.DataSource; 13 | 14 | /** 15 | * Profile 16 | * Spring为我们提供可以根据当前环境,动态的激活和切换一系列组件和功能; 17 | * @Profile :指定组件在哪个环境才能注册到容器中,不指定时,任何时候都可以注册到容器中 18 | */ 19 | @Configuration 20 | @PropertySource("classpath:/app.properties") 21 | public class MainConfigOfProfile implements EmbeddedValueResolverAware { 22 | @Value("${database.user}") 23 | private String username; 24 | @Value("${database.jdbcUrl}") 25 | private String jdbcUrl; 26 | 27 | private StringValueResolver valueResolver; 28 | private String driverClass; 29 | 30 | @Bean("devDataSource") 31 | @Profile("dev") 32 | public DataSource dateSourceDev(@Value("${database.password}") String pwd) throws Exception { 33 | ComboPooledDataSource ds = new ComboPooledDataSource(); 34 | ds.setUser(username); 35 | ds.setPassword(pwd); 36 | ds.setJdbcUrl(jdbcUrl); 37 | ds.setDriverClass(driverClass); 38 | System.out.println(ds.toString()); 39 | return ds; 40 | } 41 | 42 | @Bean("testDataSource") 43 | @Profile("test") 44 | public DataSource dateSourceTest(@Value("${database.password}") String pwd) throws Exception { 45 | ComboPooledDataSource ds = new ComboPooledDataSource(); 46 | ds.setUser(username); 47 | ds.setPassword(pwd); 48 | ds.setJdbcUrl(jdbcUrl); 49 | ds.setDriverClass(driverClass); 50 | System.out.println(ds.toString()); 51 | return ds; 52 | } 53 | 54 | @Bean("prodDataSource") 55 | @Profile("prod") 56 | public DataSource dateSourceProd(@Value("${database.password}") String pwd) throws Exception{ 57 | ComboPooledDataSource ds = new ComboPooledDataSource(); 58 | ds.setUser(username); 59 | ds.setPassword(pwd); 60 | ds.setJdbcUrl(jdbcUrl); 61 | ds.setDriverClass(driverClass); 62 | System.out.println(ds.toString()); 63 | return ds; 64 | } 65 | 66 | public void setEmbeddedValueResolver(StringValueResolver resolver) { 67 | this.valueResolver = resolver; 68 | driverClass = valueResolver.resolveStringValue("${database.driverClass}"); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/brian/config/MainConfigOfPropertyValues.java: -------------------------------------------------------------------------------- 1 | package com.brian.config; 2 | 3 | import com.brian.bean.Person; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.context.annotation.PropertySource; 7 | 8 | 9 | @Configuration 10 | @PropertySource(value = {"classpath:/app.yml"}) 11 | public class MainConfigOfPropertyValues { 12 | 13 | @Bean("person") 14 | public Person getPerson() { 15 | return new Person(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/brian/controller/BookController.java: -------------------------------------------------------------------------------- 1 | package com.brian.controller; 2 | 3 | import com.brian.service.BookService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.annotation.Qualifier; 6 | import org.springframework.stereotype.Controller; 7 | 8 | @Controller 9 | public class BookController { 10 | 11 | @Autowired 12 | //@Qualifier("bookServiceImpl") 13 | private BookService bookService; 14 | 15 | private void printBook() { 16 | bookService.printBook(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/brian/ext/BrianApplicationListener.java: -------------------------------------------------------------------------------- 1 | package com.brian.ext; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | import org.springframework.context.ApplicationListener; 5 | import org.springframework.stereotype.Component; 6 | 7 | 8 | @Component 9 | public class BrianApplicationListener implements ApplicationListener { 10 | 11 | public void onApplicationEvent(ApplicationEvent event) { 12 | System.out.println("收到的事件 => "+ event); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/brian/ext/BrianBeanDefinitionRegistryPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.brian.ext; 2 | 3 | import com.brian.bean.Alan; 4 | import org.springframework.beans.BeansException; 5 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 6 | import org.springframework.beans.factory.support.AbstractBeanDefinition; 7 | import org.springframework.beans.factory.support.BeanDefinitionBuilder; 8 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 9 | import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; 10 | import org.springframework.stereotype.Component; 11 | 12 | @Component 13 | public class BrianBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { 14 | 15 | public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { 16 | System.out.println("postProcessBeanDefinitionRegistry() => bean的数量 =>" + beanDefinitionRegistry.getBeanDefinitionCount()); 17 | AbstractBeanDefinition beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(Alan.class).getBeanDefinition(); 18 | beanDefinitionRegistry.registerBeanDefinition("alanMok",beanDefinitionBuilder); 19 | } 20 | 21 | public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { 22 | System.out.println("postProcessBeanFactory() => bean的数量 => "+ configurableListableBeanFactory.getBeanDefinitionCount()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/brian/ext/BrianBeanFactoryPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.brian.ext; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.config.BeanFactoryPostProcessor; 5 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 6 | import org.springframework.context.annotation.ComponentScan; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.Arrays; 10 | 11 | @Component 12 | public class BrianBeanFactoryPostProcessor implements BeanFactoryPostProcessor { 13 | 14 | 15 | public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { 16 | System.out.println("BrianBeanFactoryPostProcessor.postProcessBeanFactory()..."); 17 | String[] beanDefinitionNames = configurableListableBeanFactory.getBeanDefinitionNames(); 18 | int count = configurableListableBeanFactory.getBeanDefinitionCount(); 19 | System.out.println("Beans Name => " + Arrays.asList(beanDefinitionNames)); 20 | System.out.println("Beans Count => " + count); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/brian/ext/BrianService.java: -------------------------------------------------------------------------------- 1 | package com.brian.ext; 2 | 3 | 4 | import org.springframework.context.ApplicationEvent; 5 | import org.springframework.context.event.EventListener; 6 | import org.springframework.stereotype.Service; 7 | 8 | @Service 9 | public class BrianService { 10 | 11 | @EventListener 12 | public void listen(ApplicationEvent evevt){ 13 | System.out.println("@EventListener 监听到事件 => " + evevt); 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/brian/ext/ExtConfig.java: -------------------------------------------------------------------------------- 1 | package com.brian.ext; 2 | 3 | 4 | import org.springframework.context.annotation.ComponentScan; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | 8 | /** 9 | * 扩展原理: 10 | * BeanPostProcessor:bean后置处理器,bean创建对象初始化前后进行拦截的 11 | * BeanFactoryPostProcessor: beanFactory后置处理器 12 | * 在beanFactory标准初始化后调用,所有的bean定义已经保存加载到beanFactory,但bean实例还未创建 13 | * 1.ioc容器创建对象 14 | * 2.invokeBeanFactoryPostProcessors(beanFactory);执行beanFactoryPostProcessor 15 | * 1.直接在beanFactory中找到所有类型是BeanFactoryPostProcessor的组件,并执行他们的方法 16 | * 2.在初始化创建其他组件前面执行 17 | * 18 | */ 19 | @Configuration 20 | @ComponentScan("com.brian.ext") 21 | public class ExtConfig { 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/brian/mvc/BrianWebAppInitializer.java: -------------------------------------------------------------------------------- 1 | package com.brian.mvc; 2 | 3 | import com.brian.mvc.config.AppConfig; 4 | import com.brian.mvc.config.WebConfig; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; 7 | 8 | 9 | /** 10 | * web容器启动的时候创建对象: 11 | * 调用方法来初始化容器以及前端控制器 12 | */ 13 | public class BrianWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 14 | 15 | /** 16 | * 获取根容器的配置类:(Spring的配置文件) 父容器 17 | * @return 18 | */ 19 | protected Class[] getRootConfigClasses() { 20 | return new Class[]{AppConfig.class}; 21 | } 22 | 23 | /** 24 | * 获取web容器的配置类:(SpringMVC配置文件) 子容器 25 | * @return 26 | */ 27 | protected Class[] getServletConfigClasses() { 28 | return new Class[]{WebConfig.class}; 29 | } 30 | 31 | /** 32 | * 获取DispatcherServlet的映射信息 33 | * / => 拦截所有请求(包括静态资源) 不包括JSP 34 | * /* => 拦截所有请求 包括JSP页面 35 | * @return 36 | */ 37 | protected String[] getServletMappings() { 38 | return new String[]{"/"}; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/brian/mvc/config/AppConfig.java: -------------------------------------------------------------------------------- 1 | package com.brian.mvc.config; 2 | 3 | 4 | import org.springframework.context.annotation.ComponentScan; 5 | import org.springframework.context.annotation.FilterType; 6 | import org.springframework.stereotype.Controller; 7 | 8 | /** 9 | * Spring容器 不扫描controller 10 | */ 11 | @ComponentScan(value = "com.brian.mvc",excludeFilters = { 12 | @ComponentScan.Filter(type=FilterType.ANNOTATION,classes = {Controller.class}) 13 | }) 14 | public class AppConfig { 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/brian/mvc/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | package com.brian.mvc.config; 2 | 3 | 4 | import org.springframework.context.annotation.ComponentScan; 5 | import org.springframework.context.annotation.FilterType; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.web.servlet.HandlerInterceptor; 8 | import org.springframework.web.servlet.config.annotation.*; 9 | 10 | /** 11 | *SpringMVC容器 只扫描controller 12 | * useDefaultFilters = false 警用默认扫描规则(默认规则是扫描所有的) 13 | * 14 | * @EnableWebMvc 开启SpringMVC自定义配置功能 15 | */ 16 | @ComponentScan(value = "com.brian.mvc",includeFilters = { 17 | @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}) 18 | },useDefaultFilters = false) 19 | @EnableWebMvc 20 | public class WebConfig extends WebMvcConfigurerAdapter { 21 | 22 | /** 23 | * 自定义视图解析器 24 | * @param registry 25 | */ 26 | @Override 27 | public void configureViewResolvers(ViewResolverRegistry registry) { 28 | //registry.jsp(); 29 | registry.jsp("/WEB-INF/views/",".jsp"); 30 | } 31 | 32 | /** 33 | * 自定义静态资源访问 34 | * @param configurer 35 | */ 36 | @Override 37 | public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { 38 | configurer.enable(); 39 | } 40 | 41 | /** 42 | * 添加拦截器 43 | * @param registry 44 | */ 45 | @Override 46 | public void addInterceptors(InterceptorRegistry registry) { 47 | //registry.addInterceptor() TODO HandlerInterceptor 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/brian/mvc/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package com.brian.mvc.controller; 2 | 3 | 4 | import com.brian.mvc.service.TestService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.ResponseBody; 9 | 10 | @Controller 11 | public class TestController { 12 | 13 | @Autowired 14 | private TestService testService; 15 | 16 | @ResponseBody 17 | @RequestMapping("/mvc") 18 | public String testMvc(){ 19 | return testService.test(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/brian/mvc/service/TestService.java: -------------------------------------------------------------------------------- 1 | package com.brian.mvc.service; 2 | 3 | 4 | import org.springframework.stereotype.Service; 5 | 6 | @Service 7 | public class TestService { 8 | 9 | public String test(){ 10 | return "mvc test"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/brian/repository/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.brian.repository; 2 | 3 | import org.springframework.stereotype.Repository; 4 | 5 | @Repository 6 | public class BookRepository { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/brian/service/BookService.java: -------------------------------------------------------------------------------- 1 | package com.brian.service; 2 | 3 | public interface BookService { 4 | 5 | void printBook(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/brian/service/impl/BookServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.brian.service.impl; 2 | 3 | import com.brian.service.BookService; 4 | import org.springframework.stereotype.Service; 5 | 6 | /** 7 | * @program: com.annotation 8 | * @author: Brian Huang 9 | * @create: 2019-07-03 14 10 | **/ 11 | @Service 12 | public class BookServiceImpl implements BookService { 13 | @Override 14 | public void printBook() { 15 | System.out.println("---BookServiceImpl---: spring5源码分析"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/brian/service/impl/OtherBookServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.brian.service.impl; 2 | 3 | import com.brian.service.BookService; 4 | import org.springframework.context.annotation.Primary; 5 | import org.springframework.stereotype.Service; 6 | 7 | /** 8 | * @program: com.annotation 9 | * @author: Brian Huang 10 | * @create: 2019-07-03 14 11 | **/ 12 | @Service 13 | @Primary 14 | public class OtherBookServiceImpl implements BookService { 15 | @Override 16 | public void printBook() { 17 | System.out.println("---OtherBookServiceImpl---: 天道酬勤,一步一个坑"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/brian/tx/AccessRightService.java: -------------------------------------------------------------------------------- 1 | package com.brian.tx; 2 | 3 | 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Transactional; 7 | 8 | @Service 9 | public class AccessRightService { 10 | 11 | 12 | @Autowired 13 | private AccessRigntDao accessRigntDao; 14 | 15 | @Transactional 16 | public void addAccessRight() { 17 | accessRigntDao.addAccessRight(); 18 | System.out.println("add data successful..."); 19 | int i = 3/0; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/brian/tx/AccessRigntDao.java: -------------------------------------------------------------------------------- 1 | package com.brian.tx; 2 | 3 | 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.jdbc.core.JdbcTemplate; 6 | import org.springframework.stereotype.Repository; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | @Repository 10 | public class AccessRigntDao { 11 | 12 | @Autowired 13 | private JdbcTemplate jdbcTemplate; 14 | 15 | 16 | 17 | public void addAccessRight(){ 18 | String sql = "INSERT INTO tb_crc_rpt_access_right (RPAR_REPORT_ID,RPAR_USER,RPAR_USER_NAME,ID) VALUES (?,?,?,1?)"; 19 | jdbcTemplate.update(sql,"12345A","HUANG","Luser",4); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/brian/tx/TxConfig.java: -------------------------------------------------------------------------------- 1 | package com.brian.tx; 2 | 3 | 4 | import com.mchange.v2.c3p0.ComboPooledDataSource; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.ComponentScan; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.jdbc.core.JdbcTemplate; 9 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 10 | import org.springframework.transaction.PlatformTransactionManager; 11 | import org.springframework.transaction.annotation.EnableTransactionManagement; 12 | 13 | import javax.sql.DataSource; 14 | import java.beans.PropertyVetoException; 15 | 16 | /** 17 | * 1.@EnableTransactionManagement 开启基于事务的注解管理 18 | * 2.配置事务管理器来管理事务 19 | * 20 | */ 21 | 22 | /** 23 | * 声明式事务原理 24 | * 1.@EnableTransactionManagement 25 | * 利用TransactionManagementConfigurationSelector给容器中导入两个组件 26 | * AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration 27 | * 2.AutoProxyRegistrar 28 | * 给容器注册一个InfrastructureAdvisorAutoProxyCreator 29 | * =>利用后置处理器机制在创建对象以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用 30 | * 3.ProxyTransactionManagementConfiguration 31 | * 3.1 给容器中注册事务增强器 32 | * 3.1.1 事务增强器要用事务的注解信息,AnnotationTransactionAttributeSource解析事务的注解信息 33 | * 3.1.2 事务拦截器 34 | * TransactionInterceptor:保存了属性信息,事务管理器 35 | * 他是一个MethodInterceptor,在目标方法执行的时候 36 | * => 执行拦截器链 37 | * 事务拦截器 38 | * 1,先获取事务相关的属性 39 | * 2.再获取PlatformTransactionManager,如果事先没有添加指定的transactionManager,最终会从容器中 40 | * 按照类型获取一个PlatformTransactionManager. 41 | * 3.执行目标方法 42 | * 如果异常,获取到事务管理器,利用事务管理器回滚 43 | * 如果正常,获取到事务管理器,提交事务 44 | */ 45 | @Configuration 46 | @ComponentScan("com.brian.tx") 47 | @EnableTransactionManagement 48 | public class TxConfig { 49 | 50 | @Bean 51 | public DataSource dataSource() throws PropertyVetoException { 52 | ComboPooledDataSource dataSource = new ComboPooledDataSource(); 53 | dataSource.setUser("root"); 54 | dataSource.setPassword("xJ*yABGKo3GL"); 55 | dataSource.setDriverClass("com.mysql.jdbc.driver"); 56 | dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/srtest"); 57 | return dataSource; 58 | } 59 | 60 | @Bean 61 | public JdbcTemplate jdbcTemplate () throws PropertyVetoException { 62 | return new JdbcTemplate(dataSource()); 63 | } 64 | 65 | 66 | //配置事务管理器 67 | @Bean 68 | public PlatformTransactionManager platformTransactionManager () throws PropertyVetoException { 69 | return new DataSourceTransactionManager(dataSource()); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/write/annotation/BrianAnnotation.java: -------------------------------------------------------------------------------- 1 | package com.write.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 | * @interface 自定义注解 10 | * 11 | * @Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。 12 | * 在Annotation类型的声明中使用了target可更加明晰其修饰的目标。 13 | * 1. CONSTRUCTOR:用于描述构造器 14 | * 2. FIELD:用于描述域 15 | * 3. LOCAL_VARIABLE:用于描述局部变量 16 | * 4. METHOD:用于描述方法 17 | * 5. PACKAGE:用于描述包 18 | * 6. PARAMETER:用于描述参数 19 | * 7. TYPE:用于描述类、接口(包括注解类型) 或enum声明 20 | */ 21 | 22 | @Target(ElementType.METHOD) 23 | @Retention(RetentionPolicy.RUNTIME) 24 | public @interface BrianAnnotation { 25 | 26 | public int id() default 10086; 27 | public String name() default "Brian"; 28 | public String[] arrayStr(); 29 | 30 | } -------------------------------------------------------------------------------- /src/main/java/com/write/annotation/TestGetAnnotation.java: -------------------------------------------------------------------------------- 1 | package com.write.annotation; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.Arrays; 5 | import java.util.stream.Stream; 6 | 7 | /** 8 | * 测试类 9 | * 10 | * 通过JAVA反射机制 获取到注解的信息 11 | */ 12 | public class TestGetAnnotation { 13 | 14 | @BrianAnnotation(id=001,name = "Cassiel",arrayStr = {"SHE"}) 15 | public void test1(){ } 16 | 17 | public void test2(){ } 18 | 19 | public static void main(String[] args) throws ClassNotFoundException { 20 | // 21 | Class cla = Class.forName("com.write.annotation.TestGetAnnotation"); 22 | //获取当前类(不包含继承)所有的方法 23 | Method[] methods = cla.getDeclaredMethods(); 24 | 25 | Stream stream = Arrays.stream(methods); 26 | 27 | stream.forEach( m -> { 28 | System.out.println("Method Name: " + m.getName()); 29 | BrianAnnotation anno = m.getDeclaredAnnotation(BrianAnnotation.class); 30 | if(anno != null) { 31 | System.out.println("Annotation <1>: " + anno.id()); 32 | System.out.println("Annotation <2>: " + anno.name()); 33 | System.out.println("Annotation <3>: " + anno.arrayStr()); 34 | } 35 | 36 | }); 37 | 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/write/annotation/transaction/BrianTransaction.java: -------------------------------------------------------------------------------- 1 | package com.write.annotation.transaction; 2 | 3 | 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 自定义事务注解 步骤 11 | * 1.定义事务注解 12 | * 2.封装手动事务 13 | * 3.定义AOP扫包事务 14 | * 4.在拦截方法上,使用反射技术获取拦截的方法,判断改方法是有没有指定事务注解 15 | * 有就开启事务 16 | * 17 | * 注意: AOP切点定义表达定义如果不正确会倒是事务不生效,但代码也不报错 18 | * 19 | * 20 | */ 21 | @Target({ElementType.METHOD}) 22 | @Retention(RetentionPolicy.RUNTIME) 23 | public @interface BrianTransaction { 24 | 25 | } -------------------------------------------------------------------------------- /src/main/java/com/write/annotation/transaction/TransactionUtils.java: -------------------------------------------------------------------------------- 1 | package com.write.annotation.transaction; 2 | 3 | 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Scope; 6 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.transaction.TransactionStatus; 9 | import org.springframework.transaction.interceptor.DefaultTransactionAttribute; 10 | 11 | @Component 12 | @Scope("prototype") //多例模式 13 | public class TransactionUtils { 14 | 15 | @Autowired 16 | private DataSourceTransactionManager dataSourceTransactionManager; 17 | 18 | private TransactionStatus transactionStatus; 19 | 20 | /** 21 | * 开启事务 22 | * @return 23 | */ 24 | public TransactionStatus begin() { 25 | System.out.println("----------------: 开启事务"); 26 | transactionStatus = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute()); 27 | return transactionStatus; 28 | } 29 | 30 | /** 31 | * 提交事务 32 | * @param transactionStatus 33 | */ 34 | public void commit(TransactionStatus transactionStatus){ 35 | dataSourceTransactionManager.commit(transactionStatus); 36 | } 37 | 38 | /** 39 | * 事务回滚 40 | * 41 | */ 42 | public void rollback(){ 43 | if(this.transactionStatus != null){ 44 | System.out.println("----------------: 事务回滚"); 45 | dataSourceTransactionManager.rollback(this.transactionStatus); 46 | } 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/write/annotation/transaction/aop/BrianAopTransaction.java: -------------------------------------------------------------------------------- 1 | package com.write.annotation.transaction.aop; 2 | 3 | 4 | import com.write.annotation.transaction.BrianTransaction; 5 | import com.write.annotation.transaction.TransactionUtils; 6 | import org.aspectj.lang.ProceedingJoinPoint; 7 | import org.aspectj.lang.annotation.AfterThrowing; 8 | import org.aspectj.lang.annotation.Around; 9 | import org.aspectj.lang.annotation.Aspect; 10 | import org.aspectj.lang.reflect.MethodSignature; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Component; 13 | import org.springframework.transaction.TransactionStatus; 14 | 15 | import java.lang.reflect.Method; 16 | 17 | /** 18 | * 自定义事务注解 19 | */ 20 | @Aspect 21 | @Component 22 | public class BrianAopTransaction { 23 | 24 | @Autowired 25 | private TransactionUtils transactionUtils; 26 | 27 | @AfterThrowing("execution(* com.write.annotation.transaction.service.*.*(..))") 28 | public void afterThrowing(){ 29 | transactionUtils.rollback(); 30 | } 31 | 32 | @Around("execution(* com.write.annotation.transaction.service.*.*(..))") 33 | public void around(ProceedingJoinPoint pjp) throws Throwable { 34 | // 1.获取代理对象 35 | Method method = getMethod(pjp); 36 | // 2.获取该方法上是否有加上指定的注解 37 | TransactionStatus ts = null; 38 | BrianTransaction anno = method.getDeclaredAnnotation(BrianTransaction.class); 39 | if(anno != null){ 40 | // 3.如果存在事务注解则开启事务注解 41 | ts = transactionUtils.begin(); 42 | } 43 | // 4. 调用目标代理对象方法 44 | pjp.proceed(); 45 | // 5.获取该方法上是否有加上指定的注解 46 | if(ts != null){ 47 | // 6.如果存在事务注解则提交事务 48 | transactionUtils.commit(ts); 49 | } 50 | } 51 | 52 | 53 | private Method getMethod(ProceedingJoinPoint pjp) throws NoSuchMethodException { 54 | //1.1 获取方法名称 55 | String name = pjp.getSignature().getName(); 56 | //1.2 获取目标对象 57 | Class cla = pjp.getTarget().getClass(); 58 | //1.3 获取目标对象类型 59 | Class[] parameterTypes = ((MethodSignature) pjp.getSignature()).getParameterTypes(); 60 | //1.4 获取目标对象的方法 61 | Method method = cla.getMethod(name, parameterTypes); 62 | return method; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/write/annotation/transaction/config/Config.java: -------------------------------------------------------------------------------- 1 | package com.write.annotation.transaction.config; 2 | 3 | 4 | import com.mchange.v2.c3p0.ComboPooledDataSource; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.ComponentScan; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.context.annotation.EnableAspectJAutoProxy; 9 | import org.springframework.jdbc.core.JdbcTemplate; 10 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 11 | import org.springframework.transaction.annotation.EnableTransactionManagement; 12 | 13 | import javax.sql.DataSource; 14 | import java.beans.PropertyVetoException; 15 | 16 | /** 17 | * 自动装配 18 | * Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值 19 | *1).@Autowired,自动注入: 20 | * 1.默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class); 21 | * 2.如果找到多个相同类型的组件,再将属性方法的名称作为组件的id去容器中查找 22 | * applicationContext.getBean("bookDao"); 23 | * 3.@Qualifier("bookDao"):使用@Qualifier指定需要装配的组件id,而不是使用属性名 24 | * 4.自动装配默认一定要将属性赋值好,没有就会报错 25 | * 使用@Autoeired(required=false),没有默认值也不会报错 26 | * 5.@Primary, 让Spring进行自动装配的时候,默认使用首先的Bean 27 | * 28 | * 2).Spring还支持使用@Resource(JSR250)和@Inject(JSR330) [java规范的注解] 29 | * 3).@Autowired :构造器,参数,方法,属性, 30 | * 31 | */ 32 | @EnableAspectJAutoProxy //开启AOP代理自动配置 33 | @EnableTransactionManagement //基于注解的事务管理 34 | @ComponentScan(value = {"com.write.annotation.transaction"}) 35 | @Configuration 36 | public class Config { 37 | 38 | @Bean 39 | public DataSource dataSource() throws PropertyVetoException { 40 | ComboPooledDataSource dataSource = new ComboPooledDataSource(); 41 | dataSource.setJdbcUrl("jdbc:mysql://remotemysql.com:3306/khgvUiO4eh"); 42 | dataSource.setUser("khgvUiO4eh"); 43 | dataSource.setPassword("BGAAee478r"); 44 | dataSource.setDriverClass("com.mysql.jdbc.Driver"); 45 | return dataSource; 46 | } 47 | 48 | @Bean 49 | public DataSourceTransactionManager platformTransactionManager() throws PropertyVetoException { 50 | return new DataSourceTransactionManager(this.dataSource()); 51 | } 52 | 53 | @Bean 54 | public JdbcTemplate jdbcTemplate () throws PropertyVetoException { 55 | return new JdbcTemplate(this.dataSource()); 56 | } 57 | 58 | 59 | 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/write/annotation/transaction/dao/TJsonDao.java: -------------------------------------------------------------------------------- 1 | package com.write.annotation.transaction.dao; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.jdbc.core.JdbcTemplate; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public class TJsonDao { 9 | 10 | @Autowired 11 | private JdbcTemplate jdbcTemplate; 12 | 13 | public void addJson(int id, String info) { 14 | System.out.println("info: " + info); 15 | String sql = "INSERT INTO t_json(id, info) VALUES(?,?);"; 16 | int updateResult = jdbcTemplate.update(sql, id, info); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/write/annotation/transaction/service/TJsonService.java: -------------------------------------------------------------------------------- 1 | package com.write.annotation.transaction.service; 2 | 3 | 4 | import com.write.annotation.transaction.BrianTransaction; 5 | import com.write.annotation.transaction.dao.TJsonDao; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | @Service 10 | public class TJsonService { 11 | 12 | @Autowired 13 | private TJsonDao tJsonDao; 14 | 15 | @BrianTransaction 16 | public void addJson() throws Exception { 17 | tJsonDao.addJson(36,"{\"name\":\"许三多\",\"leave\":\"下士\"}"); 18 | int i = 1 / 0; 19 | tJsonDao.addJson(37,"{\"name\":\"许三多\",\"leave\":\"下士\"}"); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/write/bjdbc/BrianDbPool.java: -------------------------------------------------------------------------------- 1 | package com.write.bjdbc; 2 | 3 | import java.sql.Connection; 4 | 5 | public interface BrianDbPool { 6 | 7 | //获取连接(重复利用机制) 8 | public Connection getConnection(); 9 | 10 | //释放连接(可回收机制) 11 | public void releaseConnection(Connection connection); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/write/bjdbc/BrianDbPoolImpl.java: -------------------------------------------------------------------------------- 1 | package com.write.bjdbc; 2 | 3 | import java.sql.Connection; 4 | import java.sql.DriverManager; 5 | import java.sql.SQLException; 6 | import java.util.List; 7 | import java.util.Vector; 8 | import java.util.concurrent.atomic.AtomicInteger; 9 | 10 | /** 11 | * 数据库连接池 12 | * 1.初始化线程池(初始化空闲线程) 13 | * 2.调用getConnection方法 -->获取连接 14 | * ####2.1 先去空闲线程里面获取Connection,存放到活动线程里面去 、 15 | * 3.调用releaseConnection方法 -->释放连接 --> 资源回收 16 | * ####3.1 获取活动线程的Connection,将其转移到空闲线程里面取 17 | */ 18 | public class BrianDbPoolImpl implements BrianDbPool{ 19 | 20 | 21 | private List freeConnections = new Vector<>(); 22 | 23 | private List activeConnections = new Vector<>(); 24 | 25 | private AtomicInteger count = new AtomicInteger(); 26 | 27 | public BrianDbPoolImpl() { 28 | init(); 29 | } 30 | 31 | @Override 32 | public synchronized Connection getConnection() { 33 | Connection connection = null; 34 | //小于最大空闲连接数 35 | if(count.get() < DbBean.maxActiveConnections){ 36 | //判断空闲线程集合是否有数据 37 | if(freeConnections.size() >0 ){ 38 | //获取当前连接并移除 39 | connection = freeConnections.remove(0); 40 | }else { 41 | connection = newConnection(); 42 | } 43 | 44 | //判断连接是否可用 45 | if(isAvailable(connection)){ 46 | //将连接存放到活动线程集合中 47 | activeConnections.add(connection); 48 | }else { 49 | count.decrementAndGet(); 50 | connection = getConnection(); 51 | } 52 | 53 | }else{ 54 | //小于最大空闲连接数,进行等待 55 | try { 56 | wait(DbBean.connTimeOut); 57 | //重试 58 | connection = getConnection(); 59 | } catch (InterruptedException e) { 60 | e.printStackTrace(); 61 | return null; 62 | } 63 | } 64 | return connection; 65 | } 66 | 67 | @Override 68 | public synchronized void releaseConnection(Connection connection) { 69 | //判断连接是否可用 70 | if(isAvailable(connection)){ 71 | //判断空闲线程集合是否已经满了 72 | if(freeConnections.size() < DbBean.maxConnections) { 73 | freeConnections.add(connection); 74 | } else { 75 | try { 76 | connection.close(); 77 | } catch (SQLException e) { 78 | e.printStackTrace(); 79 | } 80 | } 81 | activeConnections.remove(connection); 82 | count.decrementAndGet(); 83 | notifyAll(); 84 | 85 | } 86 | 87 | 88 | } 89 | 90 | 91 | //初始化线程池(初始化空闲线程) 92 | private void init() { 93 | //1.获取初始化连接数 94 | for (int i = 0; i < DbBean.initConnections; i++) { 95 | //2.创建Connection连接 96 | Connection connection = newConnection(); 97 | if(connection != null){ 98 | //3.放在空闲线程freeConnections集合里面 99 | freeConnections.add(connection); 100 | } 101 | } 102 | } 103 | 104 | private Connection newConnection(){ 105 | try { 106 | Class.forName(DbBean.driverName); 107 | Connection connection = DriverManager.getConnection(DbBean.url, DbBean.userName, DbBean.password); 108 | count.incrementAndGet(); 109 | return connection; 110 | } catch (Exception e) { 111 | e.printStackTrace(); 112 | return null; 113 | } 114 | } 115 | 116 | private boolean isAvailable(Connection connection) { 117 | try { 118 | if(connection == null || connection.isClosed()) { 119 | return false; 120 | } 121 | } catch (SQLException e) { 122 | e.printStackTrace(); 123 | } 124 | return true; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/com/write/bjdbc/DbBean.java: -------------------------------------------------------------------------------- 1 | package com.write.bjdbc; 2 | 3 | public class DbBean { 4 | 5 | protected static final String driverName = "com.mysql.jdbc.Driver"; 6 | 7 | protected static String url = "jdbc:mysql://remotemysql.com:3306/khgvUiO4eh"; 8 | 9 | protected static String userName = "khgvUiO4eh"; 10 | 11 | protected static String password = "BGAAee478r"; 12 | 13 | protected static String poolName = "brian1991";// 连接池名字 14 | 15 | protected static int minConnections = 1; // 空闲池,最小连接数 16 | 17 | protected static int maxConnections = 10; // 空闲池,最大连接数 18 | 19 | protected static int initConnections = 5;// 初始化连接数 20 | 21 | protected static long connTimeOut = 1000;// 重复获得连接的频率 22 | 23 | protected static int maxActiveConnections = 100;// 最大允许的连接数,和数据库对应 24 | 25 | protected static long connectionTimeOut = 1000 * 60 * 20;// 连接超时时间,默认20分钟 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/write/blinklist/BrianLinkList.java: -------------------------------------------------------------------------------- 1 | package com.write.blinklist; 2 | 3 | /** 4 | * 手写LinkList 5 | * ####实现简单得LinkList 6 | */ 7 | public class BrianLinkList { 8 | 9 | //链表大小 10 | private int size; 11 | //第一个元素(头节点),查询从头节点开始 12 | private Node first; 13 | //最后一个元素(尾节点),添加节点从尾节点开始 14 | private Node last; 15 | 16 | //add 17 | public void add(E e){ 18 | //创建节点 19 | Node node = new Node(); 20 | node.object = e; 21 | if(first == null) { 22 | //给第一个元素赋值node节点赋值 23 | first = node; 24 | }else { 25 | //添加第二个或以上元素 26 | node.prev = last; 27 | last.next = node; 28 | } 29 | last = node; 30 | size++; 31 | } 32 | //带下标添加 33 | public void add(int index,E e){ 34 | Node newNode = new Node(); 35 | newNode.object = e; 36 | Node node = getNode(index); 37 | if(node != null){ 38 | 39 | if(isLast(node)){ 40 | //尾部添加 41 | last = newNode; 42 | last.prev = node; 43 | node.next = last; 44 | 45 | }else if(isFirst(node)){ 46 | //头部添加 47 | first = newNode; 48 | first.next = node; 49 | node.prev = first; 50 | }else{ 51 | // 52 | newNode.prev = node.prev; 53 | newNode.next = node; 54 | newNode.prev.next = newNode; 55 | newNode.next.prev = newNode; 56 | } 57 | size++; 58 | } 59 | 60 | } 61 | 62 | //从头开始查效率比较低--linklist底层是用二分法查找 63 | public Object get(int index){ 64 | return getNode(index).object; 65 | } 66 | 67 | private Node getNode(int index){ 68 | //验证下标是否有越界 69 | checkElementIndex(index); 70 | Node node = null; 71 | if(first != null){ 72 | node = first;//默认取第0个 73 | for (int i = 0; i < index; i++) { 74 | node = node.next; 75 | } 76 | } 77 | return node; 78 | } 79 | 80 | private Node getNodeofAdd(int index){ 81 | //验证下标是否有越界 82 | if(index <0 && index > size){ 83 | throw new IndexOutOfBoundsException("添加下标越界"); 84 | } 85 | Node node = null; 86 | if(first != null){ 87 | node = first;//默认取第0个 88 | for (int i = 0; i < index; i++) { 89 | node = node.next; 90 | } 91 | } 92 | return node; 93 | } 94 | 95 | private void checkElementIndex(int index){ 96 | if(!isElementIndex(index)){ 97 | throw new IndexOutOfBoundsException("查询下标越界了!"); 98 | } 99 | } 100 | 101 | private boolean isElementIndex(int index){ 102 | return index >= 0 && index < size; 103 | } 104 | 105 | //指定下标删除 106 | private void remove(int index){ 107 | //获取需要删除的元素节点 108 | Node node = getNode(index); 109 | if(node != null){ 110 | if(isFirst(node)){ 111 | //如果是头节点 112 | first.next.prev = null; 113 | first = first.next; 114 | }else if(isLast(node)){ 115 | //如果是尾节点 116 | last.prev.next = null; 117 | } else{ 118 | //获取节点的上下节点 119 | Node next = node.next; 120 | Node prev = node.prev; 121 | next.prev = prev; 122 | prev.next = next; 123 | node.object = null;//将当前值置为null方便垃圾回收器回收 124 | } 125 | size--; 126 | } 127 | } 128 | 129 | private boolean isFirst(Node node){ 130 | return node == first; 131 | } 132 | 133 | private boolean isLast(Node node){ 134 | return node == last; 135 | } 136 | 137 | //链表节点元素 138 | class Node { 139 | //存放元素的值 140 | private Object object; 141 | //上一个节点 142 | private Node prev; 143 | //下一个节点 144 | private Node next; 145 | } 146 | 147 | public static void main(String[] args) { 148 | BrianLinkList list = new BrianLinkList<>(); 149 | list.add("a"); 150 | list.add("b"); 151 | list.add("c"); 152 | list.add("d"); 153 | //list.remove(0); 154 | list.add("牛"); 155 | // list.add(4,"牛"); 156 | for (int i = 0; i < list.size; i++) { 157 | System.out.println(list.get(i)); 158 | } 159 | } 160 | 161 | 162 | } 163 | -------------------------------------------------------------------------------- /src/main/java/com/write/blist/BrianArrayList.java: -------------------------------------------------------------------------------- 1 | package com.write.blist; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * 手写ArrayList集合--底层是数组存放 7 | * 8 | * 核心API 9 | * ####1.Arrays.copyOf 数组扩容 10 | * ####2.System.arraycopy 数组拷贝 11 | */ 12 | public class BrianArrayList implements BrianList{ 13 | 14 | //底层是数组存放 15 | private Object[] elementData; 16 | 17 | //集合实际大小 18 | private int size; 19 | 20 | //初始化数组大小 21 | public BrianArrayList(int initialCapacity) { 22 | if(initialCapacity <= 0){ 23 | try { 24 | throw new Exception("初始化大小不能小于0!!!"); 25 | } catch (Exception e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | this.elementData = new Object[initialCapacity]; 30 | } 31 | 32 | //默认的初始大小为10 33 | public BrianArrayList() { 34 | this(10); 35 | } 36 | 37 | public void add(E e){ 38 | //1.判断是否需要扩容大小 39 | ensureExplicitCapacity(size+1); 40 | //2.通过下标赋值 41 | elementData[size++] = e; 42 | } 43 | 44 | public void add(int index,E e){ 45 | rangeCheckAdd(index); 46 | //1.判断是否需要扩容大小 47 | ensureExplicitCapacity(size+1); 48 | 49 | System.arraycopy(elementData,index,elementData,index+1,size-index); 50 | //2.通过下标赋值 51 | elementData[index] = e; 52 | size++; 53 | } 54 | 55 | public E get(int index){ 56 | rangeCheck(index); 57 | return elementData(index); 58 | } 59 | 60 | E elementData(int index) { 61 | return (E) elementData[index]; 62 | } 63 | 64 | public int size(){ 65 | return size; 66 | } 67 | 68 | private void rangeCheck(int index) { 69 | if(index >= size) { 70 | try { 71 | throw new Exception("大小越界了!!!"); 72 | } catch (Exception e) { 73 | e.printStackTrace(); 74 | } 75 | } 76 | } 77 | 78 | private void rangeCheckAdd(int index) { 79 | if(index > size) { 80 | try { 81 | throw new Exception("添加数据下标越界了!!!"); 82 | } catch (Exception e) { 83 | e.printStackTrace(); 84 | } 85 | } 86 | } 87 | //minCapacity最小扩容量 88 | private void ensureExplicitCapacity(int minCapacity) { 89 | //数组满了 就扩容 90 | if(size == elementData.length){ 91 | int oldCapacity = elementData.length; 92 | //扩容1.5倍 93 | int newCapacity = oldCapacity + (oldCapacity >> 1); 94 | 95 | //初始容量为1的扩容需要单独处理 96 | if(newCapacity - minCapacity <0){ 97 | newCapacity = minCapacity; 98 | } 99 | elementData = Arrays.copyOf(elementData, newCapacity); 100 | } 101 | } 102 | 103 | public E remove(int index){ 104 | rangeCheck(index); 105 | 106 | E e = get(index); 107 | //计算删除元素后面剩余元素的的长度 108 | int removeLastlenght = size - index -1; 109 | 110 | //removeLastlenght==0 表示删除末尾的元素,此时不需要复制新数组 111 | if(removeLastlenght > 0){ 112 | System.arraycopy(elementData,index+1,elementData,index,removeLastlenght); 113 | } 114 | 115 | elementData[--size] = null; 116 | return e; 117 | 118 | } 119 | 120 | public boolean remove(E e){ 121 | for (int i = 0; i < elementData.length; i++) { 122 | if(e.equals(elementData[i])){ 123 | remove(i); 124 | return true; 125 | } 126 | } 127 | return false; 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/com/write/blist/BrianList.java: -------------------------------------------------------------------------------- 1 | package com.write.blist; 2 | 3 | public interface BrianList { 4 | public void add(E e); 5 | 6 | public void add(int index,E e); 7 | 8 | public E get(int index); 9 | 10 | public E remove(int index); 11 | 12 | public boolean remove(E e); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/write/bmap/BrianHashMap.java: -------------------------------------------------------------------------------- 1 | package com.write.bmap; 2 | 3 | /** 4 | * 手写HashMap 5 | * @param 6 | * @param 7 | */ 8 | public class BrianHashMap implements BrianMap{ 9 | 10 | //定义table 存放HashMap 初始为空 用到时再new 11 | Node[] table = null; 12 | 13 | //table的大小 14 | private int size; 15 | 16 | //负载因子 负载因子的值越小,hash冲突的概率越小 17 | float DEFAULT_LOAD_FACTOR = 0.75f; 18 | 19 | //table初始大小 20 | private int DEFAULT_INITIAL_CAPACITY = 16; 21 | 22 | @Override 23 | public V put(K k, V v) { 24 | //1.判断table是否为空,为空就new一个 25 | if(table == null){ 26 | table = new Node[DEFAULT_INITIAL_CAPACITY]; 27 | } 28 | //2.判断数组是否需要扩容 29 | 30 | //扩容条件 实际大小 >= 负载因子 * 初始大小 31 | if(size >= DEFAULT_LOAD_FACTOR*DEFAULT_INITIAL_CAPACITY){ 32 | rsetSize(); 33 | } 34 | 35 | 36 | //3.计算hash值指定下标位置 37 | int index = getIndex(k, table.length); 38 | Node node = table[index]; 39 | if(node == null){ 40 | //没有下标index冲突,也即是没有node节点 41 | node = new Node<>(k,v,null); 42 | size++; 43 | }else{ 44 | Node newNode = node; 45 | while(newNode != null){ 46 | //有下标index冲突 47 | if(newNode.getKey().equals(k) || newNode.getKey() == k){ 48 | //hashCode相同 key equals也相同表示同一个对象 49 | return newNode.setValue(v); 50 | }else{ 51 | //hashCode相同 key不同表示不同的对象 52 | //新的node的next节点就是原来的node 53 | //遍历到最后一个node 54 | if(newNode.next == null){ 55 | node = new Node<>(k,v,node); 56 | size++; 57 | } 58 | 59 | } 60 | newNode = newNode.next; 61 | } 62 | } 63 | table[index] = node; 64 | return null; 65 | } 66 | 67 | //table扩容 68 | private void rsetSize(){ 69 | //1.生成新的table是原来的2倍 70 | Node[] newTables = new Node[table.length << 1]; 71 | //2.重新计算index的索引,存放发哦新的table里面 72 | for (int i = 0; i < table.length ; i++) { 73 | Node oldNode = table[i]; 74 | 75 | while(oldNode != null){ 76 | table[i] = null;//通知回收垃圾 77 | //重新计算index 78 | int newIndex = getIndex(oldNode.key, newTables.length); 79 | Node oldNext = oldNode.next; 80 | //如果index在新的table中发生index冲突,则以链表存储 81 | oldNode.next = newTables[newIndex]; 82 | //将之前table的node赋值给新的table 83 | newTables[newIndex] = oldNode; 84 | //判断是否继续遍历 85 | oldNode = oldNext; 86 | 87 | } 88 | } 89 | //3.给新的table赋值 90 | table = newTables; 91 | DEFAULT_INITIAL_CAPACITY = newTables.length; 92 | newTables = null; 93 | 94 | 95 | } 96 | 97 | //打印hashMap全部元素 98 | public void print(){ 99 | for (int i = 0; i < table.length; i++) { 100 | System.out.print("Map集合下标位置:" + i + " <<>> "); 101 | Node node = table[i]; 102 | while(node != null){ 103 | System.out.print(" {key: " + node.key + "- value: " + node.value + "} "); 104 | node = node.next; 105 | } 106 | System.out.println(); 107 | } 108 | } 109 | 110 | private int getIndex(K k,int length){ 111 | int hashCode = k.hashCode(); 112 | return hashCode % length; 113 | 114 | } 115 | 116 | @Override 117 | public V get(K k) { 118 | Node node = table[getIndex(k, table.length)]; 119 | 120 | Node resNode = getNode(node, k); 121 | return resNode == null ? null: resNode.value; 122 | 123 | } 124 | 125 | private Node getNode(Node node,K k){ 126 | while(node != null){ 127 | if(node.key.equals(k) || node.key == k){ 128 | return node; 129 | } 130 | node = node.next; 131 | } 132 | return null; 133 | } 134 | 135 | @Override 136 | public int size() { 137 | return this.size; 138 | } 139 | 140 | 141 | //定义节点 单向链表 142 | class Node implements Entry{ 143 | 144 | //集合的key 145 | private K key; 146 | //集合的value 147 | private V value; 148 | //下一个节点 149 | private Node next; 150 | 151 | public Node(K key, V value, Node next) { 152 | this.key = key; 153 | this.value = value; 154 | this.next = next; 155 | } 156 | 157 | @Override 158 | public K getKey() { 159 | return this.key; 160 | } 161 | 162 | @Override 163 | public V getValue() { 164 | return this.value; 165 | } 166 | 167 | @Override 168 | public V setValue(V value) { 169 | //设置新值的时候返回老的值 170 | V oldValue = this.value; 171 | this.value = value; 172 | return oldValue; 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /src/main/java/com/write/bmap/BrianMap.java: -------------------------------------------------------------------------------- 1 | package com.write.bmap; 2 | 3 | /** 4 | *手写JDK1.7 HashMap 数组+单向链表 5 | */ 6 | public interface BrianMap { 7 | 8 | //向集合中插入数据 9 | public V put(K k, V v); 10 | 11 | //从集合中取数据 12 | public V get(K k); 13 | 14 | //集合大小 15 | public int size(); 16 | 17 | 18 | //Entry 19 | interface Entry{ 20 | K getKey(); 21 | 22 | V getValue(); 23 | 24 | V setValue(V value); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/write/bmvc/annotation/BrianController.java: -------------------------------------------------------------------------------- 1 | package com.write.bmvc.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 | * 10 | */ 11 | @Target({ElementType.TYPE}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface BrianController { 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/write/bmvc/annotation/BrianRequestMapping.java: -------------------------------------------------------------------------------- 1 | package com.write.bmvc.annotation; 2 | 3 | 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | 10 | @Target({ElementType.TYPE,ElementType.METHOD}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | public @interface BrianRequestMapping { 13 | 14 | String[] value() default {}; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/write/bmvc/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package com.write.bmvc.controller; 2 | 3 | 4 | import com.write.bmvc.annotation.BrianController; 5 | import com.write.bmvc.annotation.BrianRequestMapping; 6 | 7 | @BrianController 8 | @BrianRequestMapping("/brian") 9 | public class TestController { 10 | 11 | 12 | @BrianRequestMapping("/test") 13 | public String test() { 14 | 15 | System.out.println("手写springMV框架...."); 16 | return "BRIAN"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/write/bmvc/servlet/BrianDispatcherServlet.java: -------------------------------------------------------------------------------- 1 | package com.write.bmvc.servlet; 2 | 3 | import com.write.bmvc.annotation.BrianController; 4 | import com.write.bmvc.annotation.BrianRequestMapping; 5 | import com.write.bservice.annotation.utils.ClassUtil; 6 | import org.springframework.util.StringUtils; 7 | 8 | import javax.servlet.ServletException; 9 | import javax.servlet.http.HttpServlet; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.IOException; 13 | import java.lang.reflect.Method; 14 | import java.util.Arrays; 15 | import java.util.List; 16 | import java.util.concurrent.ConcurrentHashMap; 17 | 18 | /** 19 | * 自定义前端控制器 20 | * 21 | * 1.创建一个前端控制器 BrianDispatcherServlet 拦截所有请求 (基于servlet实现) 22 | * 2.初始化操作 重写servlet init()方法 23 | * ####2.1 扫描包,将包下范围所有的类,注入到springMVC容器里面去 24 | * ####2.2 将URL映射和方法关联 25 | * #######2.2.1 判断类上是否有注解,通过java反射机循环遍历方法,判断方法上是否有注解,进行封装URL和方法对应 26 | * 3.处理请求,重写servlet的doGet()或者doPost()方法 27 | * ####3.1 获取请求url, 去urlBeans获取实例对象,成功湖区实例后,调用urlMethods获取方法名称,使用java反射机制执行方法 28 | * 29 | */ 30 | public class BrianDispatcherServlet extends HttpServlet { 31 | 32 | //springMVC 容器 {key:类名Id, value:对象} 33 | private ConcurrentHashMap springmvcBeans = new ConcurrentHashMap<>(); 34 | //springMVC 容器 {key:url请求地址, value: Controller对象} 35 | private ConcurrentHashMap urlBeans = new ConcurrentHashMap<>(); 36 | //springMVC 容器 {key:url请求地址, value: Controller对象里面的方法的名称} 37 | private ConcurrentHashMap urlMethods = new ConcurrentHashMap<>(); 38 | 39 | @Override 40 | public void init() throws ServletException { 41 | //1. 扫描当前包下所有的类 42 | List> classes = ClassUtil.getClasses("com.write.bmvc.controller"); 43 | //2.将类放到springMVC容器中 44 | putIntoMvcContainer(classes); 45 | //3.将url和方法进行关联 46 | handlerMapping(); 47 | } 48 | 49 | @Override 50 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 51 | doPost(req,resp); 52 | } 53 | 54 | @Override 55 | protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { 56 | //处理请求 57 | //1.获取请求的url地址 58 | String requestURI = req.getRequestURI(); 59 | if(StringUtils.isEmpty(requestURI)){ 60 | return; 61 | } 62 | //2.从Map集合中获取控制对象 63 | Object obj = urlBeans.get(requestURI); 64 | if(obj != null){ 65 | resp.getWriter().write("url not found 404!!!"); 66 | return; 67 | } 68 | //3.使用url获取方法 69 | String methodName = urlMethods.get(requestURI); 70 | if(StringUtils.isEmpty(methodName)){ 71 | resp.getWriter().write("method not found 404!!!"); 72 | } 73 | //4.使用java机制执行方法 74 | String resultPage = (String) methodInvoke(obj, methodName); 75 | resp.getWriter().write(resultPage); 76 | //5.使用java反射机制获取方法的返回结果 77 | //6.调用试图转换器渲染给页面展示 78 | 79 | 80 | 81 | 82 | 83 | 84 | } 85 | 86 | 87 | private Object methodInvoke(Object obj,String methodName){ 88 | Class cls = obj.getClass(); 89 | Method method = null; 90 | try { 91 | method = cls.getDeclaredMethod(methodName); 92 | Object result = method.invoke(obj); 93 | return result; 94 | 95 | } catch (Exception e) { 96 | e.printStackTrace(); 97 | return null; 98 | } 99 | 100 | 101 | } 102 | 103 | private void putIntoMvcContainer(List> classes){ 104 | classes.stream().forEach(cla -> { 105 | //判断类上是否有加注解 106 | BrianController declaredAnnotation = cla.getDeclaredAnnotation(BrianController.class); 107 | if(declaredAnnotation != null) { 108 | String beanId = ClassUtil.toLowerCaseFirstOne(cla.getSimpleName()); 109 | try { 110 | Object obj = newInstance(cla); 111 | springmvcBeans.put(beanId,obj); 112 | } catch (Exception e) { 113 | e.printStackTrace(); 114 | } 115 | } 116 | }); 117 | } 118 | 119 | //实例化对象 120 | private Object newInstance(Class cla) throws Exception { 121 | return cla.newInstance(); 122 | } 123 | 124 | private void handlerMapping(){ 125 | //1.遍历springMVC容器,判断Bean对象上是否有@BrianRequestMapping url映射注解 126 | springmvcBeans.entrySet().stream().forEach(bean -> { 127 | Object value = bean.getValue(); 128 | //判断类上是否有加注解 129 | BrianRequestMapping declaredAnnotation = value.getClass().getDeclaredAnnotation(BrianRequestMapping.class); 130 | String baseUrl = ""; 131 | if(declaredAnnotation != null){ 132 | //获取类上的url映射地址 133 | baseUrl = declaredAnnotation.value().toString(); 134 | } 135 | //判断类里面的方法是否有加注解 136 | String finalBaseUrl = baseUrl; 137 | Arrays.stream(value.getClass().getFields()).forEach(method -> { 138 | BrianRequestMapping declaredAnnotation1 = method.getDeclaredAnnotation(BrianRequestMapping.class); 139 | String methodUrl = ""; 140 | if(declaredAnnotation1 != null) { 141 | //获取方法上的url映射地址 142 | methodUrl = finalBaseUrl + declaredAnnotation1.value().toString(); 143 | //springMVC 容器 {key:url请求地址, value: Controller对象} 144 | urlBeans.put(finalBaseUrl,bean); 145 | //springMVC 容器 {key:url请求地址, value: Controller对象里面的方法的名称} 146 | urlMethods.put(methodUrl,method.getName()); 147 | } 148 | }); 149 | }); 150 | 151 | 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/main/java/com/write/bmybatis/domain/TJson.java: -------------------------------------------------------------------------------- 1 | package com.write.bmybatis.domain; 2 | 3 | public class TJson { 4 | 5 | private int id; 6 | private Object info; 7 | 8 | public int getId() { 9 | return id; 10 | } 11 | 12 | public void setId(int id) { 13 | this.id = id; 14 | } 15 | 16 | public Object getInfo() { 17 | return info; 18 | } 19 | 20 | public void setInfo(Object info) { 21 | this.info = info; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "TJson{" + 27 | "id=" + id + 28 | ", info=" + info + 29 | '}'; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/write/bmybatis/mapper/TJsonMapper.java: -------------------------------------------------------------------------------- 1 | package com.write.bmybatis.mapper; 2 | 3 | import com.write.bmybatis.domain.TJson; 4 | import com.write.bmybatis.orm.annotaton.BrianInsert; 5 | import com.write.bmybatis.orm.annotaton.BrianParam; 6 | import com.write.bmybatis.orm.annotaton.BrianSelect; 7 | 8 | public interface TJsonMapper { 9 | 10 | 11 | @BrianInsert("insert into t_json(id,info) values(#{id},#{info})") 12 | int insertJson(@BrianParam("id") int id,@BrianParam("info") Object info); 13 | 14 | @BrianSelect("select * from t_json where id= #{id}") 15 | TJson sleectJsonById(@BrianParam("id") int id); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/write/bmybatis/orm/annotaton/BrianInsert.java: -------------------------------------------------------------------------------- 1 | package com.write.bmybatis.orm.annotaton; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 自定义插入注解 7 | */ 8 | @Documented 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Target(ElementType.METHOD) 11 | public @interface BrianInsert { 12 | 13 | String value(); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/write/bmybatis/orm/annotaton/BrianParam.java: -------------------------------------------------------------------------------- 1 | package com.write.bmybatis.orm.annotaton; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 自定义参数注解 7 | */ 8 | @Documented 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Target(ElementType.PARAMETER) 11 | public @interface BrianParam { 12 | String value(); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/write/bmybatis/orm/annotaton/BrianSelect.java: -------------------------------------------------------------------------------- 1 | package com.write.bmybatis.orm.annotaton; 2 | 3 | 4 | import java.lang.annotation.*; 5 | 6 | /** 7 | * 自定义查询注解 8 | */ 9 | @Documented 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Target(ElementType.METHOD) 12 | public @interface BrianSelect { 13 | 14 | String value(); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/write/bmybatis/orm/aop/BrianInvocationHandler.java: -------------------------------------------------------------------------------- 1 | package com.write.bmybatis.orm.aop; 2 | 3 | import com.write.bmybatis.orm.annotaton.BrianInsert; 4 | import com.write.bmybatis.orm.annotaton.BrianParam; 5 | import com.write.bmybatis.orm.annotaton.BrianSelect; 6 | import com.write.bmybatis.utils.JDBCUtils; 7 | import com.write.bmybatis.utils.SQLUtils; 8 | 9 | import java.lang.reflect.Field; 10 | import java.lang.reflect.InvocationHandler; 11 | import java.lang.reflect.Method; 12 | import java.lang.reflect.Parameter; 13 | import java.sql.ResultSet; 14 | import java.sql.SQLException; 15 | import java.util.ArrayList; 16 | import java.util.Arrays; 17 | import java.util.List; 18 | import java.util.concurrent.ConcurrentHashMap; 19 | 20 | /** 21 | * 使用反射到动态代理技术拦截接口 22 | */ 23 | public class BrianInvocationHandler implements InvocationHandler { 24 | 25 | private Object object; 26 | 27 | public BrianInvocationHandler(Object object) { 28 | this.object = object; 29 | } 30 | 31 | /** 32 | * 33 | * @param proxy 代理对象 34 | * @param method 拦截的方法 35 | * @param args 方法上的参数 36 | * @return 37 | * @throws Throwable 38 | */ 39 | @Override 40 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 41 | 42 | Object result; 43 | 44 | //insert 45 | result = doInsert(method, args); 46 | 47 | //select 48 | result = doQuery(method, args); 49 | 50 | return result; 51 | } 52 | 53 | 54 | private Object doQuery(Method method, Object[] args) throws Exception { 55 | //1.判断方法上是否有@BrianInsert注解 56 | BrianSelect select = method.getDeclaredAnnotation(BrianSelect.class); 57 | if (select != null) { 58 | //2.获取该注解的上的query语句 59 | String strSql = select.value(); 60 | //3.获取参数方法上的参数和sql里面的参数匹配 61 | //定义一个Map集合 key为@BrianQuery的参数,value为方法参数 62 | //获取方法上的参数 63 | ConcurrentHashMap paramsMap = mappingData(method, args); 64 | 65 | List sqlParams = new ArrayList<>(); 66 | List strings = SQLUtils.sqlSelectParameter(strSql); 67 | strings.stream().forEach(paramName -> { 68 | sqlParams.add(paramsMap.get(paramName)); 69 | }); 70 | //4.替换参数为? 71 | String newSql = SQLUtils.parameQuestion(strSql, strings); 72 | System.out.println("-----sql-----: " + newSql); 73 | 74 | //5.调用JDBC底层代码执行语句 75 | ResultSet query = JDBCUtils.query(newSql, sqlParams); 76 | 77 | //6.获取返回类型 78 | Class returnType = method.getReturnType(); 79 | 80 | 81 | if(!query.next()) { 82 | return null; 83 | } 84 | 85 | //向前移动一位 86 | query.previous(); 87 | Object resultObject = returnType.newInstance(); 88 | 89 | while(query.next()){ 90 | for (String param: strings) { 91 | //获取集合中的数据 92 | Object value = query.getObject(param); 93 | Field field = returnType.getDeclaredField(param); 94 | field.setAccessible(true); 95 | field.set(resultObject,value); 96 | } 97 | } 98 | 99 | return resultObject; 100 | } 101 | 102 | return null; 103 | 104 | } 105 | private int doInsert(Method method, Object[] args){ 106 | //1.判断方法上是否有@BrianInsert注解 107 | BrianInsert brianInsert = method.getDeclaredAnnotation(BrianInsert.class); 108 | if(brianInsert != null){ 109 | //2.获取该注解的上的insert语句 110 | String strSql = brianInsert.value(); 111 | //3.获取参数方法上的参数和sql里面的参数匹配 112 | //定义一个Map集合 key为@BrianInsert的参数,value为方法参数 113 | //获取方法上的参数 114 | ConcurrentHashMap paramsMap = mappingData(method, args); 115 | 116 | List sqlParams = new ArrayList<>(); 117 | String[] strings = SQLUtils.sqlInsertParameter(strSql); 118 | Arrays.stream(strings).forEach(paramName -> { 119 | sqlParams.add(paramsMap.get(paramName)); 120 | }); 121 | //4.替换参数为? 122 | String newSql = SQLUtils.parameQuestion(strSql, strings); 123 | System.out.println("-----sql-----: " + newSql); 124 | 125 | //5.调用JDBC底层代码执行语句 126 | return JDBCUtils.insert(newSql,false,sqlParams); 127 | } 128 | return 0; 129 | } 130 | 131 | private ConcurrentHashMap mappingData(Method method, Object[] args){ 132 | ConcurrentHashMap paramsMaps = new ConcurrentHashMap<>(); 133 | Parameter[] parameters = method.getParameters(); 134 | for (int i = 0; i < parameters.length; i++) { 135 | Parameter parameter = parameters[i]; 136 | BrianParam brianParam = parameter.getAnnotation(BrianParam.class); 137 | if(brianParam != null) { 138 | //参数名称 139 | String paramName = brianParam.value(); 140 | Object paramValue = args[i]; 141 | paramsMaps.put(paramName,paramValue); 142 | } 143 | } 144 | return paramsMaps; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/com/write/bmybatis/sql/SqlSession.java: -------------------------------------------------------------------------------- 1 | package com.write.bmybatis.sql; 2 | 3 | import com.write.bmybatis.orm.aop.BrianInvocationHandler; 4 | 5 | import java.lang.reflect.Proxy; 6 | 7 | public class SqlSession { 8 | 9 | /** 10 | * 加载Mapper接口 11 | * @param cls 12 | * @param 13 | * @return 14 | */ 15 | public static T getMapper(Class cls){ 16 | return (T) Proxy.newProxyInstance(cls.getClassLoader(),new Class[]{cls},new BrianInvocationHandler(cls)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/write/bmybatis/utils/JDBCUtils.java: -------------------------------------------------------------------------------- 1 | package com.write.bmybatis.utils; 2 | 3 | import java.sql.Connection; 4 | import java.sql.DriverManager; 5 | import java.sql.PreparedStatement; 6 | import java.sql.ResultSet; 7 | import java.sql.ResultSetMetaData; 8 | import java.sql.SQLException; 9 | import java.sql.Statement; 10 | import java.util.ArrayList; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | public final class JDBCUtils { 16 | 17 | private static String connect; 18 | private static String driverClassName; 19 | private static String URL; 20 | private static String username; 21 | private static String password; 22 | private static boolean autoCommit; 23 | 24 | /** 声明一个 Connection类型的静态属性,用来缓存一个已经存在的连接对象 */ 25 | private static Connection conn; 26 | 27 | static { 28 | config(); 29 | } 30 | 31 | /** 32 | * 开头配置自己的数据库信息 33 | */ 34 | private static void config() { 35 | /* 36 | * 获取驱动 37 | */ 38 | driverClassName = "com.mysql.jdbc.Driver"; 39 | /* 40 | * 获取URL 41 | */ 42 | URL = "jdbc:mysql://remotemysql.com:3306/khgvUiO4eh?useUnicode=true&characterEncoding=utf8"; 43 | /* 44 | * 获取用户名 45 | */ 46 | username = "khgvUiO4eh"; 47 | /* 48 | * 获取密码 49 | */ 50 | password = "BGAAee478r"; 51 | /* 52 | * 设置是否自动提交,一般为false不用改 53 | */ 54 | autoCommit = false; 55 | 56 | } 57 | 58 | /** 59 | * 载入数据库驱动类 60 | */ 61 | private static boolean load() { 62 | try { 63 | Class.forName(driverClassName); 64 | return true; 65 | } catch (ClassNotFoundException e) { 66 | System.out.println("驱动类 " + driverClassName + " 加载失败"); 67 | } 68 | 69 | return false; 70 | } 71 | 72 | /** 73 | * 专门检查缓存的连接是否不可以被使用 ,不可以被使用的话,就返回 true 74 | */ 75 | private static boolean invalid() { 76 | if (conn != null) { 77 | try { 78 | if (conn.isClosed() || !conn.isValid(3)) { 79 | return true; 80 | /* 81 | * isValid方法是判断Connection是否有效,如果连接尚未关闭并且仍然有效,则返回 true 82 | */ 83 | } 84 | } catch (SQLException e) { 85 | e.printStackTrace(); 86 | } 87 | /* 88 | * conn 既不是 null 且也没有关闭 ,且 isValid 返回 true,说明是可以使用的 ( 返回 false ) 89 | */ 90 | return false; 91 | } else { 92 | return true; 93 | } 94 | } 95 | 96 | /** 97 | * 建立数据库连接 98 | */ 99 | public static Connection connect() { 100 | if (invalid()) { /* invalid为true时,说明连接是失败的 */ 101 | /* 加载驱动 */ 102 | load(); 103 | try { 104 | /* 建立连接 */ 105 | conn = DriverManager.getConnection(URL, username, password); 106 | } catch (SQLException e) { 107 | System.out.println("建立 " + connect + " 数据库连接失败 , " + e.getMessage()); 108 | } 109 | } 110 | return conn; 111 | } 112 | 113 | /** 114 | * 设置是否自动提交事务 115 | **/ 116 | public static void transaction() { 117 | 118 | try { 119 | conn.setAutoCommit(autoCommit); 120 | } catch (SQLException e) { 121 | System.out.println("设置事务的提交方式为 : " + (autoCommit ? "自动提交" : "手动提交") + " 时失败: " + e.getMessage()); 122 | } 123 | 124 | } 125 | 126 | /** 127 | * 创建 Statement 对象 128 | */ 129 | public static Statement statement() { 130 | Statement st = null; 131 | connect(); 132 | /* 如果连接是无效的就重新连接 */ 133 | transaction(); 134 | /* 设置事务的提交方式 */ 135 | try { 136 | st = conn.createStatement(); 137 | } catch (SQLException e) { 138 | System.out.println("创建 Statement 对象失败: " + e.getMessage()); 139 | } 140 | 141 | return st; 142 | } 143 | 144 | /** 145 | * 根据给定的带参数占位符的SQL语句,创建 PreparedStatement 对象 146 | * 147 | * @param SQL 148 | * 带参数占位符的SQL语句 149 | * @return 返回相应的 PreparedStatement 对象 150 | */ 151 | private static PreparedStatement prepare(String SQL, boolean autoGeneratedKeys) { 152 | 153 | PreparedStatement ps = null; 154 | connect(); 155 | /* 如果连接是无效的就重新连接 */ 156 | transaction(); 157 | /* 设置事务的提交方式 */ 158 | try { 159 | if (autoGeneratedKeys) { 160 | ps = conn.prepareStatement(SQL, Statement.RETURN_GENERATED_KEYS); 161 | } else { 162 | ps = conn.prepareStatement(SQL); 163 | } 164 | } catch (SQLException e) { 165 | System.out.println("创建 PreparedStatement 对象失败: " + e.getMessage()); 166 | } 167 | 168 | return ps; 169 | 170 | } 171 | 172 | public static ResultSet query(String SQL, List params) { 173 | 174 | if (SQL == null || SQL.trim().isEmpty() || !SQL.trim().toLowerCase().startsWith("select")) { 175 | throw new RuntimeException("你的SQL语句为空或不是查询语句"); 176 | } 177 | ResultSet rs = null; 178 | if (params.size() > 0) { 179 | /* 说明 有参数 传入,就需要处理参数 */ 180 | PreparedStatement ps = prepare(SQL, false); 181 | try { 182 | for (int i = 0; i < params.size(); i++) { 183 | ps.setObject(i + 1, params.get(i)); 184 | } 185 | rs = ps.executeQuery(); 186 | } catch (SQLException e) { 187 | System.out.println("执行SQL失败: " + e.getMessage()); 188 | } 189 | } else { 190 | /* 说明没有传入任何参数 */ 191 | Statement st = statement(); 192 | try { 193 | rs = st.executeQuery(SQL); // 直接执行不带参数的 SQL 语句 194 | } catch (SQLException e) { 195 | System.out.println("执行SQL失败: " + e.getMessage()); 196 | } 197 | } 198 | 199 | return rs; 200 | 201 | } 202 | 203 | private static Object typeof(Object o) { 204 | Object r = o; 205 | 206 | if (o instanceof java.sql.Timestamp) { 207 | return r; 208 | } 209 | // 将 java.util.Date 转成 java.sql.Date 210 | if (o instanceof java.util.Date) { 211 | java.util.Date d = (java.util.Date) o; 212 | r = new java.sql.Date(d.getTime()); 213 | return r; 214 | } 215 | // 将 Character 或 char 变成 String 216 | if (o instanceof Character || o.getClass() == char.class) { 217 | r = String.valueOf(o); 218 | return r; 219 | } 220 | return r; 221 | } 222 | 223 | public static boolean execute(String SQL, Object... params) { 224 | if (SQL == null || SQL.trim().isEmpty() || SQL.trim().toLowerCase().startsWith("select")) { 225 | throw new RuntimeException("你的SQL语句为空或有错"); 226 | } 227 | boolean r = false; 228 | /* 表示 执行 DDL 或 DML 操作是否成功的一个标识变量 */ 229 | 230 | /* 获得 被执行的 SQL 语句的 前缀 */ 231 | SQL = SQL.trim(); 232 | SQL = SQL.toLowerCase(); 233 | String prefix = SQL.substring(0, SQL.indexOf(" ")); 234 | String operation = ""; // 用来保存操作类型的 变量 235 | // 根据前缀 确定操作 236 | switch (prefix) { 237 | case "create": 238 | operation = "create table"; 239 | break; 240 | case "alter": 241 | operation = "update table"; 242 | break; 243 | case "drop": 244 | operation = "drop table"; 245 | break; 246 | case "truncate": 247 | operation = "truncate table"; 248 | break; 249 | case "insert": 250 | operation = "insert :"; 251 | break; 252 | case "update": 253 | operation = "update :"; 254 | break; 255 | case "delete": 256 | operation = "delete :"; 257 | break; 258 | } 259 | if (params.length > 0) { // 说明有参数 260 | PreparedStatement ps = prepare(SQL, false); 261 | Connection c = null; 262 | try { 263 | c = ps.getConnection(); 264 | } catch (SQLException e) { 265 | e.printStackTrace(); 266 | } 267 | try { 268 | for (int i = 0; i < params.length; i++) { 269 | Object p = params[i]; 270 | p = typeof(p); 271 | ps.setObject(i + 1, p); 272 | } 273 | ps.executeUpdate(); 274 | commit(c); 275 | r = true; 276 | } catch (SQLException e) { 277 | System.out.println(operation + " 失败: " + e.getMessage()); 278 | rollback(c); 279 | } 280 | 281 | } else { // 说明没有参数 282 | 283 | Statement st = statement(); 284 | Connection c = null; 285 | try { 286 | c = st.getConnection(); 287 | } catch (SQLException e) { 288 | e.printStackTrace(); 289 | } 290 | // 执行 DDL 或 DML 语句,并返回执行结果 291 | try { 292 | st.executeUpdate(SQL); 293 | commit(c); // 提交事务 294 | r = true; 295 | } catch (SQLException e) { 296 | System.out.println(operation + " 失败: " + e.getMessage()); 297 | rollback(c); // 回滚事务 298 | } 299 | } 300 | return r; 301 | } 302 | 303 | /* 304 | * 305 | * @param SQL 需要执行的 INSERT 语句 306 | * 307 | * @param autoGeneratedKeys 指示是否需要返回由数据库产生的键 308 | * 309 | * @param params 将要执行的SQL语句中包含的参数占位符的 参数值 310 | * 311 | * @return 如果指定 autoGeneratedKeys 为 true 则返回由数据库产生的键; 如果指定 autoGeneratedKeys 312 | * 为 false 则返回受当前SQL影响的记录数目 313 | */ 314 | public static int insert(String SQL, boolean autoGeneratedKeys, List params) { 315 | int var = -1; 316 | if (SQL == null || SQL.trim().isEmpty()) { 317 | throw new RuntimeException("你没有指定SQL语句,请检查是否指定了需要执行的SQL语句"); 318 | } 319 | // 如果不是 insert 开头开头的语句 320 | if (!SQL.trim().toLowerCase().startsWith("insert")) { 321 | System.out.println(SQL.toLowerCase()); 322 | throw new RuntimeException("你指定的SQL语句不是插入语句,请检查你的SQL语句"); 323 | } 324 | // 获得 被执行的 SQL 语句的 前缀 ( 第一个单词 ) 325 | SQL = SQL.trim(); 326 | SQL = SQL.toLowerCase(); 327 | if (params.size() > 0) { // 说明有参数 328 | PreparedStatement ps = prepare(SQL, autoGeneratedKeys); 329 | Connection c = null; 330 | try { 331 | c = ps.getConnection(); // 从 PreparedStatement 对象中获得 它对应的连接对象 332 | } catch (SQLException e) { 333 | e.printStackTrace(); 334 | } 335 | try { 336 | for (int i = 0; i < params.size(); i++) { 337 | Object p = params.get(i); 338 | p = typeof(p); 339 | ps.setObject(i + 1, p); 340 | } 341 | int count = ps.executeUpdate(); 342 | if (autoGeneratedKeys) { // 如果希望获得数据库产生的键 343 | ResultSet rs = ps.getGeneratedKeys(); // 获得数据库产生的键集 344 | if (rs.next()) { // 因为是保存的是单条记录,因此至多返回一个键 345 | var = rs.getInt(1); // 获得值并赋值给 var 变量 346 | } 347 | } else { 348 | var = count; // 如果不需要获得,则将受SQL影像的记录数赋值给 var 变量 349 | } 350 | commit(c); 351 | } catch (SQLException e) { 352 | System.out.println("数据保存失败: " + e.getMessage()); 353 | rollback(c); 354 | } 355 | } else { // 说明没有参数 356 | Statement st = statement(); 357 | Connection c = null; 358 | try { 359 | c = st.getConnection(); // 从 Statement 对象中获得 它对应的连接对象 360 | } catch (SQLException e) { 361 | e.printStackTrace(); 362 | } 363 | // 执行 DDL 或 DML 语句,并返回执行结果 364 | try { 365 | int count = st.executeUpdate(SQL); 366 | if (autoGeneratedKeys) { // 如果企望获得数据库产生的键 367 | ResultSet rs = st.getGeneratedKeys(); // 获得数据库产生的键集 368 | if (rs.next()) { // 因为是保存的是单条记录,因此至多返回一个键 369 | var = rs.getInt(1); // 获得值并赋值给 var 变量 370 | } 371 | } else { 372 | var = count; // 如果不需要获得,则将受SQL影像的记录数赋值给 var 变量 373 | } 374 | commit(c); // 提交事务 375 | } catch (SQLException e) { 376 | System.out.println("数据保存失败: " + e.getMessage()); 377 | rollback(c); // 回滚事务 378 | } 379 | } 380 | return var; 381 | } 382 | 383 | /** 提交事务 */ 384 | private static void commit(Connection c) { 385 | if (c != null && !autoCommit) { 386 | try { 387 | c.commit(); 388 | } catch (SQLException e) { 389 | e.printStackTrace(); 390 | } 391 | } 392 | } 393 | 394 | /** 回滚事务 */ 395 | private static void rollback(Connection c) { 396 | if (c != null && !autoCommit) { 397 | try { 398 | c.rollback(); 399 | } catch (SQLException e) { 400 | e.printStackTrace(); 401 | } 402 | } 403 | } 404 | 405 | /** 406 | * 释放资源 407 | **/ 408 | public static void release(Object cloaseable) { 409 | 410 | if (cloaseable != null) { 411 | 412 | if (cloaseable instanceof ResultSet) { 413 | ResultSet rs = (ResultSet) cloaseable; 414 | try { 415 | rs.close(); 416 | } catch (SQLException e) { 417 | e.printStackTrace(); 418 | } 419 | } 420 | 421 | if (cloaseable instanceof Statement) { 422 | Statement st = (Statement) cloaseable; 423 | try { 424 | st.close(); 425 | } catch (SQLException e) { 426 | e.printStackTrace(); 427 | } 428 | } 429 | 430 | if (cloaseable instanceof Connection) { 431 | Connection c = (Connection) cloaseable; 432 | try { 433 | c.close(); 434 | } catch (SQLException e) { 435 | e.printStackTrace(); 436 | } 437 | } 438 | 439 | } 440 | 441 | } 442 | 443 | } -------------------------------------------------------------------------------- /src/main/java/com/write/bmybatis/utils/SQLUtils.java: -------------------------------------------------------------------------------- 1 | package com.write.bmybatis.utils; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | 7 | public class SQLUtils { 8 | /** 9 | * 10 | * 获取Insert语句后面values 参数信息 11 | * @param sql 12 | * @return 13 | */ 14 | public static String[] sqlInsertParameter(String sql) { 15 | int startIndex = sql.indexOf("values"); 16 | int endIndex = sql.length(); 17 | String substring = sql.substring(startIndex + 6, endIndex).replace("(", "").replace(")", "").replace("#{", "") 18 | .replace("}", ""); 19 | String[] split = substring.split(","); 20 | return split; 21 | } 22 | 23 | /** 24 | * 25 | * 获取select 后面where语句 26 | * @param sql 27 | * @return 28 | */ 29 | public static List sqlSelectParameter(String sql) { 30 | int startIndex = sql.indexOf("where"); 31 | int endIndex = sql.length(); 32 | String substring = sql.substring(startIndex + 5, endIndex); 33 | String[] split = substring.split("and"); 34 | List listArr = new ArrayList<>(); 35 | for (String string : split) { 36 | String[] sp2 = string.split("="); 37 | listArr.add(sp2[0].trim()); 38 | } 39 | return listArr; 40 | } 41 | 42 | /** 43 | * 将SQL语句的参数替换变为? 44 | * @param sql 45 | * @param parameterName 46 | * @return 47 | */ 48 | public static String parameQuestion(String sql, String[] parameterName) { 49 | for (int i = 0; i < parameterName.length; i++) { 50 | String string = parameterName[i]; 51 | sql = sql.replace("#{" + string + "}", "?"); 52 | } 53 | return sql; 54 | } 55 | 56 | public static String parameQuestion(String sql, List parameterName) { 57 | for (int i = 0; i < parameterName.size(); i++) { 58 | String string = parameterName.get(i); 59 | sql = sql.replace("#{" + string + "}", "?"); 60 | } 61 | return sql; 62 | } 63 | 64 | public static void main(String[] args) { 65 | 66 | List sqlSelectParameter = SQLUtils 67 | .sqlSelectParameter("select * from User where userName=#{userName} and userAge=#{userAge} "); 68 | for (String string : sqlSelectParameter) { 69 | System.out.println(string); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/write/bservice/BrianAnnotationConfigApplicationContext.java: -------------------------------------------------------------------------------- 1 | package com.write.bservice; 2 | 3 | import com.write.bservice.annotation.BrianResource; 4 | import com.write.bservice.annotation.BrianService; 5 | import com.write.bservice.annotation.utils.ClassUtil; 6 | 7 | import java.lang.reflect.Field; 8 | import java.util.Arrays; 9 | import java.util.List; 10 | import java.util.concurrent.ConcurrentHashMap; 11 | 12 | /** 13 | *自定义注解版本的 IOC容器 14 | */ 15 | public class BrianAnnotationConfigApplicationContext { 16 | 17 | //扫描的包 18 | private String packageName; 19 | 20 | private ConcurrentHashMap beans = null; 21 | 22 | public BrianAnnotationConfigApplicationContext(String packageName) throws Exception { 23 | beans = new ConcurrentHashMap<>(); 24 | this.packageName = packageName; 25 | initBeans(); 26 | initFields(); 27 | } 28 | 29 | public Object getBean(String beanId) throws Exception { 30 | if(beanId == null || beanId.isEmpty()){ 31 | throw new Exception("beanId不能为空"); 32 | } 33 | String id = ClassUtil.toLowerCaseFirstOne(beanId); 34 | return beans.get(id); 35 | } 36 | 37 | /** 38 | * 初始化对象 39 | * 1.使用java反射机制扫描包并获取改包下面所有的类 40 | * 2.判断类上是否存在注入bean的注解 41 | * 3.使用java反射机制进行初始化 42 | */ 43 | public void initBeans() throws Exception { 44 | //1.使用java反射机制扫描包并获取改包下面所有的类 45 | List> classes = ClassUtil.getClasses(packageName); 46 | //2.判断类上是否存在注入bean的注解 47 | ConcurrentHashMap exitAnnotation = findClassExitAnnotation(classes); 48 | if(exitAnnotation == null || exitAnnotation.isEmpty()){ 49 | throw new Exception("扫描的包下面没有任何类加上@BrianService注解"); 50 | } 51 | } 52 | 53 | public ConcurrentHashMap findClassExitAnnotation(List> classes){ 54 | classes.stream().forEach(bean -> { 55 | BrianService annotation = bean.getAnnotation(BrianService.class); 56 | if(annotation != null){ 57 | //获取当前类名 58 | String className = bean.getSimpleName(); 59 | //存放beanid (类名首字母小写) 60 | String beanId = ClassUtil.toLowerCaseFirstOne(className); 61 | try { 62 | //3.使用java反射机制进行初始化 63 | beans.put(beanId, bean.newInstance()); 64 | } catch (Exception e) { 65 | e.printStackTrace(); 66 | } 67 | } 68 | }); 69 | return beans; 70 | } 71 | 72 | /** 73 | * 依赖注入注解原理 74 | * 1.使用反射机制,获取当前类的所有属性 75 | * 2.判断当前类的属性上是否有加注解 76 | * 3.默认使用属性名称去IOC容器查找对应的bean对象 77 | */ 78 | 79 | public void attrAssign(Object object){ 80 | //1.使用反射机制,获取当前类的所有属性 81 | Class aClass1 = object.getClass(); 82 | Field[] fields = aClass1.getDeclaredFields(); 83 | //2.判断当前类的属性上是否有加注解 84 | Arrays.stream(fields).forEach(field -> { 85 | BrianResource brianResource = field.getAnnotation(BrianResource.class); 86 | if(brianResource != null){ 87 | //获取属性名称 88 | String fieldName = field.getName(); 89 | Object obj = beans.get(fieldName); 90 | if(obj != null){ 91 | //3.默认使用属性名称去IOC容器查找对应的bean对象 92 | //允许访问私有属性 93 | field.setAccessible(true); 94 | try { 95 | //参数1当前对象 ,参数2当前属性的bean对象 96 | field.set(object,obj); 97 | } catch (IllegalAccessException e) { 98 | e.printStackTrace(); 99 | } 100 | } 101 | } 102 | }); 103 | } 104 | 105 | //初始化属性 106 | public void initFields(){ 107 | beans.entrySet().stream().forEach(value -> { 108 | Object v = value.getValue(); 109 | attrAssign(v); 110 | }); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/com/write/bservice/annotation/BrianResource.java: -------------------------------------------------------------------------------- 1 | package com.write.bservice.annotation; 2 | 3 | 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 自定义注解 11 | */ 12 | @Target({ElementType.FIELD}) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface BrianResource { 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/write/bservice/annotation/BrianService.java: -------------------------------------------------------------------------------- 1 | package com.write.bservice.annotation; 2 | 3 | 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 自定义注解 11 | */ 12 | @Target({ElementType.TYPE}) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface BrianService { 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/write/bservice/annotation/service/BaseService.java: -------------------------------------------------------------------------------- 1 | package com.write.bservice.annotation.service; 2 | 3 | 4 | import com.write.bservice.annotation.BrianResource; 5 | import com.write.bservice.annotation.BrianService; 6 | 7 | @BrianService 8 | public class BaseService { 9 | 10 | 11 | @BrianResource 12 | private OtherService otherService; 13 | 14 | public BaseService() { 15 | System.out.println("------ BaseService init-------"); 16 | } 17 | 18 | public void add(){ 19 | otherService.add(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/write/bservice/annotation/service/OtherService.java: -------------------------------------------------------------------------------- 1 | package com.write.bservice.annotation.service; 2 | 3 | import com.write.bservice.annotation.BrianService; 4 | 5 | @BrianService 6 | public class OtherService { 7 | 8 | public void add() { 9 | System.out.println("---OtherService--- add()---"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/write/bservice/annotation/utils/ClassUtil.java: -------------------------------------------------------------------------------- 1 | package com.write.bservice.annotation.utils; 2 | 3 | import java.io.File; 4 | import java.io.FileFilter; 5 | import java.io.IOException; 6 | import java.net.JarURLConnection; 7 | import java.net.URL; 8 | import java.net.URLDecoder; 9 | import java.util.ArrayList; 10 | import java.util.Enumeration; 11 | import java.util.List; 12 | import java.util.jar.JarEntry; 13 | import java.util.jar.JarFile; 14 | 15 | public class ClassUtil { 16 | 17 | /** 18 | * 取得某个接口下所有实现这个接口的类 19 | */ 20 | public static List getAllClassByInterface(Class c) { 21 | List returnClassList = null; 22 | 23 | if (c.isInterface()) { 24 | // 获取当前的包名 25 | String packageName = c.getPackage().getName(); 26 | // 获取当前包下以及子包下所以的类 27 | List> allClass = getClasses(packageName); 28 | if (allClass != null) { 29 | returnClassList = new ArrayList(); 30 | for (Class classes : allClass) { 31 | // 判断是否是同一个接口 32 | if (c.isAssignableFrom(classes)) { 33 | // 本身不加入进去 34 | if (!c.equals(classes)) { 35 | returnClassList.add(classes); 36 | } 37 | } 38 | } 39 | } 40 | } 41 | 42 | return returnClassList; 43 | } 44 | 45 | /* 46 | * 取得某一类所在包的所有类名 不含迭代 47 | */ 48 | public static String[] getPackageAllClassName(String classLocation, String packageName) { 49 | // 将packageName分解 50 | String[] packagePathSplit = packageName.split("[.]"); 51 | String realClassLocation = classLocation; 52 | int packageLength = packagePathSplit.length; 53 | for (int i = 0; i < packageLength; i++) { 54 | realClassLocation = realClassLocation + File.separator + packagePathSplit[i]; 55 | } 56 | File packeageDir = new File(realClassLocation); 57 | if (packeageDir.isDirectory()) { 58 | String[] allClassName = packeageDir.list(); 59 | return allClassName; 60 | } 61 | return null; 62 | } 63 | 64 | /** 65 | * 从包package中获取所有的Class 66 | * 67 | * @param packageName 68 | * @return 69 | */ 70 | public static List> getClasses(String packageName) { 71 | 72 | // 第一个class类的集合 73 | List> classes = new ArrayList>(); 74 | // 是否循环迭代 75 | boolean recursive = true; 76 | // 获取包的名字 并进行替换 77 | String packageDirName = packageName.replace('.', '/'); 78 | // 定义一个枚举的集合 并进行循环来处理这个目录下的things 79 | Enumeration dirs; 80 | try { 81 | dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName); 82 | // 循环迭代下去 83 | while (dirs.hasMoreElements()) { 84 | // 获取下一个元素 85 | URL url = dirs.nextElement(); 86 | // 得到协议的名称 87 | String protocol = url.getProtocol(); 88 | // 如果是以文件的形式保存在服务器上 89 | if ("file".equals(protocol)) { 90 | // 获取包的物理路径 91 | String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); 92 | // 以文件的方式扫描整个包下的文件 并添加到集合中 93 | findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes); 94 | } else if ("jar".equals(protocol)) { 95 | // 如果是jar包文件 96 | // 定义一个JarFile 97 | JarFile jar; 98 | try { 99 | // 获取jar 100 | jar = ((JarURLConnection) url.openConnection()).getJarFile(); 101 | // 从此jar包 得到一个枚举类 102 | Enumeration entries = jar.entries(); 103 | // 同样的进行循环迭代 104 | while (entries.hasMoreElements()) { 105 | // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件 106 | JarEntry entry = entries.nextElement(); 107 | String name = entry.getName(); 108 | // 如果是以/开头的 109 | if (name.charAt(0) == '/') { 110 | // 获取后面的字符串 111 | name = name.substring(1); 112 | } 113 | // 如果前半部分和定义的包名相同 114 | if (name.startsWith(packageDirName)) { 115 | int idx = name.lastIndexOf('/'); 116 | // 如果以"/"结尾 是一个包 117 | if (idx != -1) { 118 | // 获取包名 把"/"替换成"." 119 | packageName = name.substring(0, idx).replace('/', '.'); 120 | } 121 | // 如果可以迭代下去 并且是一个包 122 | if ((idx != -1) || recursive) { 123 | // 如果是一个.class文件 而且不是目录 124 | if (name.endsWith(".class") && !entry.isDirectory()) { 125 | // 去掉后面的".class" 获取真正的类名 126 | String className = name.substring(packageName.length() + 1, name.length() - 6); 127 | try { 128 | // 添加到classes 129 | classes.add(Class.forName(packageName + '.' + className)); 130 | } catch (ClassNotFoundException e) { 131 | e.printStackTrace(); 132 | } 133 | } 134 | } 135 | } 136 | } 137 | } catch (IOException e) { 138 | e.printStackTrace(); 139 | } 140 | } 141 | } 142 | } catch (IOException e) { 143 | e.printStackTrace(); 144 | } 145 | 146 | return classes; 147 | } 148 | 149 | /** 150 | * 以文件的形式来获取包下的所有Class 151 | * 152 | * @param packageName 153 | * @param packagePath 154 | * @param recursive 155 | * @param classes 156 | */ 157 | public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive, 158 | List> classes) { 159 | // 获取此包的目录 建立一个File 160 | File dir = new File(packagePath); 161 | // 如果不存在或者 也不是目录就直接返回 162 | if (!dir.exists() || !dir.isDirectory()) { 163 | return; 164 | } 165 | // 如果存在 就获取包下的所有文件 包括目录 166 | File[] dirfiles = dir.listFiles(new FileFilter() { 167 | // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件) 168 | public boolean accept(File file) { 169 | return (recursive && file.isDirectory()) || (file.getName().endsWith(".class")); 170 | } 171 | }); 172 | // 循环所有文件 173 | for (File file : dirfiles) { 174 | // 如果是目录 则继续扫描 175 | if (file.isDirectory()) { 176 | findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, 177 | classes); 178 | } else { 179 | // 如果是java类文件 去掉后面的.class 只留下类名 180 | String className = file.getName().substring(0, file.getName().length() - 6); 181 | try { 182 | // 添加到集合中去 183 | classes.add(Class.forName(packageName + '.' + className)); 184 | } catch (ClassNotFoundException e) { 185 | e.printStackTrace(); 186 | } 187 | } 188 | } 189 | } 190 | 191 | 192 | // 首字母转小写 193 | public static String toLowerCaseFirstOne(String s) { 194 | if (Character.isLowerCase(s.charAt(0))) 195 | return s; 196 | else 197 | return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString(); 198 | } 199 | } -------------------------------------------------------------------------------- /src/main/resources/SpringSources.txt: -------------------------------------------------------------------------------- 1 | Spring容器的refresh() [创建刷新] 2 | 1.prepareRefresh(); 刷新前的预处理工作 3 | 1.initPropertySources();初始化一些属性设置;子类自定义个性化的属性设置方法 4 | 2.getEnvironment().validateRequiredProperties(); 检验属性合法等 5 | 3.this.earlyApplicationEvents = new LinkedHashSet();保存容器的早起的一些事件 6 | 2.obtainFreshBeanFactory();获取BeanFactory 7 | 1.refreshBeanFactory();刷新 [创建] BeanFactory 8 | 创建一个this.beanFactory = new DefaultListableBeanFactory(); 9 | 设置ID 10 | 2.getBeanFactory();返回刚才ConfigurableListableBeanFactory创建的beanFactory对象; 11 | 3.将创建的BeanFactory 【DefaultListableBeanFactory】返回; 12 | 3.prepareBeanFactory(beanFactory);BeanFactory的预准备工作(BeanFactory进行一些设置) 13 | 1.设置BeanFactory的类加载器,支持表达式解析器。。。 14 | 2.添加部分BeanPostProcessor【ApplicationContextAwareProcessor】 15 | 3.设置忽略的自动装配的接口 EnvironmentAware,EmbeddedValueResolverAware。。。。 16 | 4.注册可以解析的自动装配;我们能在任何组件中自动注入: 17 | BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext 18 | 5.添加后置处理器BeanPostProcessor【ApplicationListenerDetector】 19 | 6.添加编译时的AspectJ 20 | 7.给BeanFactory中注册一些可用的组件: 21 | environment【ConfigurableEnvironment】, 22 | systemProperties【Map】, 23 | systemEnvironment【Map】 24 | 4.postProcessBeanFactory(beanFactory);BeanFactory准备工作完成以后进行的后置处理工作 25 | 1.子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置 26 | ====================================以上是BeanFactory的创建及预准备工作======== 27 | -------------------------------------------------------------------------------- /src/main/resources/app.properties: -------------------------------------------------------------------------------- 1 | database.user = khgvUiO4eh 2 | database.password = BGAAee478r 3 | database.jdbcUrl = jdbc:mysql://remotemysql.com:3306/khgvUiO4eh 4 | database.jdbcUrl.prod = jdbc:mysql://localhost:3306/srtest 5 | database.driverClass = com.mysql.jdbc.Driver 6 | database02.name = test -------------------------------------------------------------------------------- /src/main/resources/app.yml: -------------------------------------------------------------------------------- 1 | database: 2 | name: remote_test_db 3 | database02: 4 | name: test -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | brianDispatcherServlet 8 | com.write.bmvc.servlet.BrianDispatcherServlet 9 | 1 10 | 11 | 12 | brianDispatcherServlet 13 | 14 | / 15 | 16 | -------------------------------------------------------------------------------- /src/test/java/BASEIC_LIST_TEST.java: -------------------------------------------------------------------------------- 1 | import com.write.blist.BrianArrayList; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class BASEIC_LIST_TEST { 6 | 7 | public static void main(String[] args) { 8 | BrianArrayList arrayList = new BrianArrayList(1); 9 | arrayList.add("过桥米线"); 10 | arrayList.add("过桥拉面"); 11 | arrayList.add("火锅"); 12 | arrayList.add("烤鱼"); 13 | // arrayList.remove(1); 14 | // arrayList.remove("过桥米线"); 15 | arrayList.add(4,"兰州拉面"); 16 | for (int i = 0; i map = new BrianHashMap<>(); 8 | map.put("1","100"); 9 | map.put("2","200"); 10 | map.put("3","300"); 11 | map.put("4","400"); 12 | map.put("5","500"); 13 | 14 | map.put("11","1100"); 15 | map.put("12","1200"); 16 | map.put("13","1300"); 17 | map.put("14","1400"); 18 | map.put("15","1500"); 19 | map.put("16","1600"); 20 | map.put("16","16AA"); 21 | 22 | map.put("22","2200"); 23 | map.put("22","22AA"); 24 | map.put("23","2300"); 25 | map.put("24","2400"); 26 | 27 | map.put("11","11AA"); 28 | map.put("25","11AA"); 29 | map.put("26","11AA"); 30 | map.put("27","11AA"); 31 | map.put("28","11AA"); 32 | map.put("29","11AA"); 33 | map.put("30","11AA"); 34 | map.put("31","11AA"); 35 | map.put("32","11AA"); 36 | /* map.put("33","11AA"); 37 | map.put("34","11AA"); 38 | map.put("35","11AA"); 39 | map.put("36","11AA"); 40 | map.put("37","11AA"); 41 | map.put("38","11AA");*/ 42 | 43 | map.print(); 44 | System.out.println(map.get("11")); 45 | 46 | 47 | int a =10086; 48 | System.out.println(~a); 49 | 50 | } 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/IOC_TEST_AOP.java: -------------------------------------------------------------------------------- 1 | import com.brian.aop.MathCalculator; 2 | import com.brian.bean.Brian; 3 | import com.brian.config.MainConfigOfAOP; 4 | import com.brian.config.MainConfigOfAutowired; 5 | import com.write.bservice.BrianAnnotationConfigApplicationContext; 6 | import com.write.bservice.annotation.service.BaseService; 7 | import org.junit.Ignore; 8 | import org.junit.Test; 9 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 10 | 11 | import java.util.Random; 12 | 13 | public class IOC_TEST_AOP { 14 | 15 | @Test 16 | @Ignore 17 | public void test() { 18 | AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(MainConfigOfAOP.class); 19 | MathCalculator mc = app.getBean(MathCalculator.class); 20 | mc.div(15,3); 21 | app.close(); 22 | } 23 | 24 | public static void main(String[] args) throws Exception{ 25 | BrianAnnotationConfigApplicationContext brianAnnotationConfigApplicationContext = 26 | new BrianAnnotationConfigApplicationContext("com.write.bservice.annotation"); 27 | 28 | BaseService baseService = (BaseService) brianAnnotationConfigApplicationContext.getBean("baseService"); 29 | baseService.add(); 30 | 31 | } 32 | 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/IOC_TEST_Autowired.java: -------------------------------------------------------------------------------- 1 | import com.write.annotation.transaction.config.Config; 2 | import com.write.annotation.transaction.service.TJsonService; 3 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 4 | 5 | import java.util.Arrays; 6 | 7 | public class IOC_TEST_Autowired { 8 | 9 | public static void main(String[] args) throws Exception { 10 | AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Config.class); 11 | 12 | // Arrays.stream(app.getBeanDefinitionNames()).forEach( bean -> { 13 | // System.out.println("Bean Name: " + bean ); 14 | // }); 15 | TJsonService bean = app.getBean(TJsonService.class); 16 | bean.addJson(); 17 | 18 | 19 | } 20 | 21 | 22 | 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/IOC_TEST_EXT.java: -------------------------------------------------------------------------------- 1 | import com.brian.ext.ExtConfig; 2 | import org.junit.Test; 3 | import org.springframework.context.ApplicationEvent; 4 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 5 | 6 | 7 | 8 | public class IOC_TEST_EXT { 9 | 10 | @Test 11 | public void test() { 12 | AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(ExtConfig.class); 13 | //发布事件 14 | app.publishEvent(new ApplicationEvent(new String("自定义的事件")) { 15 | 16 | }); 17 | app.close(); 18 | 19 | } 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/IOC_TEST_PropertyValues.java: -------------------------------------------------------------------------------- 1 | import com.brian.bean.Person; 2 | import com.brian.config.MainConfigOfPropertyValues; 3 | import org.junit.Test; 4 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 5 | import org.springframework.core.env.ConfigurableEnvironment; 6 | 7 | 8 | public class IOC_TEST_PropertyValues { 9 | 10 | @Test 11 | public void testValues () { 12 | AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(MainConfigOfPropertyValues.class); 13 | Person p = (Person) app.getBean("person"); 14 | System.out.println(p); 15 | 16 | ConfigurableEnvironment ce = app.getEnvironment(); 17 | 18 | 19 | String s = ce.getProperty("database.name"); 20 | System.out.println(s); 21 | 22 | 23 | 24 | 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/IOC_TEST_TX.java: -------------------------------------------------------------------------------- 1 | import com.brian.aop.MathCalculator; 2 | import com.brian.config.MainConfigOfAOP; 3 | import com.brian.tx.AccessRightService; 4 | import com.brian.tx.TxConfig; 5 | import org.junit.Test; 6 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 7 | 8 | public class IOC_TEST_TX { 9 | 10 | @Test 11 | public void test() { 12 | AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(TxConfig.class); 13 | AccessRightService accessRightService = app.getBean(AccessRightService.class); 14 | accessRightService.addAccessRight(); 15 | app.close(); 16 | 17 | } 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/IOC_test_Profile.java: -------------------------------------------------------------------------------- 1 | import com.brian.config.MainConfigOfProfile; 2 | import org.junit.Test; 3 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 4 | 5 | import javax.sql.DataSource; 6 | 7 | public class IOC_test_Profile { 8 | 9 | @Test 10 | public void test() { 11 | /*AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfigOfProfile.class); 12 | String[] beanNamesForType = ac.getBeanNamesForType(DataSource.class); 13 | for (int i = 0; i < beanNamesForType.length; i++) { 14 | System.out.println(beanNamesForType[i]); 15 | }*/ 16 | 17 | 18 | //设置启动的环境 19 | AnnotationConfigApplicationContext sc = new AnnotationConfigApplicationContext(); 20 | sc.getEnvironment().setActiveProfiles("test","dev"); 21 | //注册主配置 22 | sc.register(MainConfigOfProfile.class); 23 | //启动刷新容器 24 | sc.refresh(); 25 | String[] beanNamesForType = sc.getBeanNamesForType(DataSource.class); 26 | for (int i = 0; i < beanNamesForType.length; i++) { 27 | System.out.println(beanNamesForType[i]); 28 | } 29 | 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/JDBC_TEST_CONNECT.java: -------------------------------------------------------------------------------- 1 | import com.write.bjdbc.BrianDbPool; 2 | import com.write.bjdbc.BrianDbPoolImpl; 3 | 4 | import java.sql.Connection; 5 | 6 | /** 7 | * 手写数据库连接池 (核心参数:空闲线程,核心线程) 8 | * 1.初始化线程池(初始化空闲线程) 9 | * 2.调用getConnection方法 -->获取连接 10 | * ####2.1 先去空闲线程里面获取Connection,存放到活动线程里面去 、 11 | * 3.调用releaseConnection方法 -->释放连接 --> 资源回收 12 | *####3.1 获取活动线程的Connection,将其转移到空闲线程里面取 13 | * 14 | */ 15 | public class JDBC_TEST_CONNECT { 16 | 17 | public static void main(String[] args) { 18 | ThreadPool threadPool = new ThreadPool(); 19 | for (int i = 0; i <5; i++) { 20 | new Thread(threadPool).start(); 21 | } 22 | } 23 | } 24 | 25 | class ThreadPool implements Runnable { 26 | 27 | @Override 28 | public void run() { 29 | BrianDbPool brianDbPool = new BrianDbPoolImpl(); 30 | for (int i = 0; i <100; i++) { 31 | Connection connection = brianDbPool.getConnection(); 32 | System.out.println(Thread.currentThread().getName() + " <<>> " + connection); 33 | brianDbPool.releaseConnection(connection); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/test/java/MYBATIS_TEST_ORM.java: -------------------------------------------------------------------------------- 1 | import com.write.bmybatis.domain.TJson; 2 | import com.write.bmybatis.mapper.TJsonMapper; 3 | import com.write.bmybatis.sql.SqlSession; 4 | 5 | /** 6 | * 7 | */ 8 | public class MYBATIS_TEST_ORM { 9 | 10 | public static void main(String[] args) { 11 | TJsonMapper mapper = SqlSession.getMapper(TJsonMapper.class); 12 | // int insertResult = mapper.insertJson(2, "{\"name\":\"张三毛\"}"); 13 | 14 | // System.out.println("返回影响行数:" + insertResult); 15 | 16 | TJson tJson = mapper.sleectJsonById(1); 17 | System.out.println("查询结果: " + tJson); 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/MianTest.java: -------------------------------------------------------------------------------- 1 | import com.brian.config.MainConfig; 2 | import org.junit.Test; 3 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 4 | 5 | public class MianTest { 6 | 7 | @Test 8 | public void test01 () { 9 | AnnotationConfigApplicationContext acac = 10 | new AnnotationConfigApplicationContext(MainConfig.class); 11 | String[] list = acac.getBeanDefinitionNames(); 12 | for (int i = 0; i < list.length; i++) { 13 | System.out.println(list[i]); 14 | 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /target/classes/SpringSources.txt: -------------------------------------------------------------------------------- 1 | Spring容器的refresh() [创建刷新] 2 | 1.prepareRefresh(); 刷新前的预处理工作 3 | 1.initPropertySources();初始化一些属性设置;子类自定义个性化的属性设置方法 4 | 2.getEnvironment().validateRequiredProperties(); 检验属性合法等 5 | 3.this.earlyApplicationEvents = new LinkedHashSet();保存容器的早起的一些事件 6 | 2.obtainFreshBeanFactory();获取BeanFactory 7 | 1.refreshBeanFactory();刷新 [创建] BeanFactory 8 | 创建一个this.beanFactory = new DefaultListableBeanFactory(); 9 | 设置ID 10 | 2.getBeanFactory();返回刚才ConfigurableListableBeanFactory创建的beanFactory对象; 11 | 3.将创建的BeanFactory 【DefaultListableBeanFactory】返回; 12 | 3.prepareBeanFactory(beanFactory);BeanFactory的预准备工作(BeanFactory进行一些设置) 13 | 1.设置BeanFactory的类加载器,支持表达式解析器。。。 14 | 2.添加部分BeanPostProcessor【ApplicationContextAwareProcessor】 15 | 3.设置忽略的自动装配的接口 EnvironmentAware,EmbeddedValueResolverAware。。。。 16 | 4.注册可以解析的自动装配;我们能在任何组件中自动注入: 17 | BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext 18 | 5.添加后置处理器BeanPostProcessor【ApplicationListenerDetector】 19 | 6.添加编译时的AspectJ 20 | 7.给BeanFactory中注册一些可用的组件: 21 | environment【ConfigurableEnvironment】, 22 | systemProperties【Map】, 23 | systemEnvironment【Map】 24 | 4.postProcessBeanFactory(beanFactory);BeanFactory准备工作完成以后进行的后置处理工作 25 | 1.子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置 26 | ====================================以上是BeanFactory的创建及预准备工作======== 27 | -------------------------------------------------------------------------------- /target/classes/app.properties: -------------------------------------------------------------------------------- 1 | database.user = khgvUiO4eh 2 | database.password = BGAAee478r 3 | database.jdbcUrl = jdbc:mysql://remotemysql.com:3306/khgvUiO4eh 4 | database.jdbcUrl.prod = jdbc:mysql://localhost:3306/srtest 5 | database.driverClass = com.mysql.jdbc.Driver 6 | database02.name = test -------------------------------------------------------------------------------- /target/classes/app.yml: -------------------------------------------------------------------------------- 1 | database: 2 | name: remote_test_db 3 | database02: 4 | name: test -------------------------------------------------------------------------------- /target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/showkawa/spring-annotation/1a04b7d5a32bcfb2e074dba5ea3362643a3d6d30/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst -------------------------------------------------------------------------------- /target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst: -------------------------------------------------------------------------------- 1 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/config/MainConfigOfProfile.java 2 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bservice/annotation/service/OtherService.java 3 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/tx/AccessRigntDao.java 4 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/tx/TxConfig.java 5 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/annotation/BrianAnnotation.java 6 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bmybatis/orm/annotaton/BrianInsert.java 7 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/config/MainConfigOfAOP.java 8 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/service/impl/OtherBookServiceImpl.java 9 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/service/BookService.java 10 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bmap/BrianMap.java 11 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/mvc/controller/TestController.java 12 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/config/MainConfigOfLifeCycle.java 13 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/mvc/config/AppConfig.java 14 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bservice/annotation/service/BaseService.java 15 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/aop/LogAspects.java 16 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/ext/BrianBeanDefinitionRegistryPostProcessor.java 17 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bjdbc/BrianDbPoolImpl.java 18 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/bean/WenTao.java 19 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/bean/Vincent.java 20 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/config/MainConfig.java 21 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/service/impl/BookServiceImpl.java 22 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/mvc/BrianWebAppInitializer.java 23 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/MainTest.java 24 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bservice/annotation/BrianService.java 25 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bmybatis/domain/TJson.java 26 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bmvc/annotation/BrianController.java 27 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bmybatis/utils/SQLUtils.java 28 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bservice/annotation/BrianResource.java 29 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/mvc/config/WebConfig.java 30 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bmybatis/mapper/TJsonMapper.java 31 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bmybatis/orm/annotaton/BrianSelect.java 32 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/blist/BrianArrayList.java 33 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/mvc/service/TestService.java 34 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/ext/BrianBeanFactoryPostProcessor.java 35 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/condition/BrianCondition.java 36 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/blist/BrianList.java 37 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bmybatis/orm/annotaton/BrianParam.java 38 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/blinklist/BrianLinkList.java 39 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/controller/BookController.java 40 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bmybatis/utils/JDBCUtils.java 41 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/annotation/transaction/BrianTransaction.java 42 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bjdbc/DbBean.java 43 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bmybatis/sql/SqlSession.java 44 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/annotation/transaction/config/Config.java 45 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/config/BrianTypeFilter.java 46 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bservice/BrianAnnotationConfigApplicationContext.java 47 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/repository/BookRepository.java 48 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bjdbc/BrianDbPool.java 49 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/annotation/transaction/service/TJsonService.java 50 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/bean/Brian.java 51 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/tx/AccessRightService.java 52 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/annotation/transaction/TransactionUtils.java 53 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bmap/BrianHashMap.java 54 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/aop/MathCalculator.java 55 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/condition/BrianSelector.java 56 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bmvc/annotation/BrianRequestMapping.java 57 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/config/MainConfigOfPropertyValues.java 58 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/ext/BrianService.java 59 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bservice/annotation/utils/ClassUtil.java 60 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/annotation/TestGetAnnotation.java 61 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/config/MainConfigOfAutowired.java 62 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bmvc/controller/TestController.java 63 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/bean/Alan.java 64 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/bean/BrianBeanFactory.java 65 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/annotation/transaction/dao/TJsonDao.java 66 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/bean/Person.java 67 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bmvc/servlet/BrianDispatcherServlet.java 68 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/async/DeferredResult02.java 69 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/bmybatis/orm/aop/BrianInvocationHandler.java 70 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/async/ResultQueue.java 71 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/ext/ExtConfig.java 72 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/ext/BrianApplicationListener.java 73 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/brian/async/Callable01.java 74 | /home/brian/桌面/just-do-it/code/spring-annotation/src/main/java/com/write/annotation/transaction/aop/BrianAopTransaction.java 75 | --------------------------------------------------------------------------------