[Java] SpringDemo

摘要:
IoC/DI函数配置解析:将配置文件解析为BeanDefinition结构,方便BeanFactory创建对象对象创建:BeanFactory根据配置文件通过反射创建对象对象生命周期管理,形成ApplicationContext:执行条目ClassPathXmlApplicationContext:ApplicationContext的实现类BeanConfigParser:将配置文件解析为Be

IoC/DI

功能

  • 配置解析:将配置文件解析为BeanDefinition结构,便于BeansFactory创建对象
  • 对象创建:BeansFactory根据配置文件通过反射创建对象
  • 对象生命周期管理

组成

  • ApplicationContext:执行入口
  • ClassPathXmlApplicationContext:ApplicationContext 的实现类
  • BeanConfigParser:将配置文件解析为 BeanDefinition
  • XmlBeanConfigParser:BeanConfigParser 的实现类
  • BeanDefinition:类的定义
  • BeansFactory:根据配置文件解析得到的 BeanDefinition 创建对象
  • RateLimiter.java:要创建的对象
  • RedisCounter.java:RateLImiter 的依赖类
  • DiDemo:主程序
  • beans.xml:配置文件

[Java] SpringDemo第1张

过程

  • src下新建 xml 配置文件
  • 传入配置文件名beans.xml,获取ClassPathXmlApplicationContext对象的实例applicationContext
  • 通过applicationContext,获取目标对象rateLimiter

代码

ApplicationContext

[Java] SpringDemo第2张[Java] SpringDemo第3张
1 package di;
2 
3 public interface ApplicationContext {
4     Object getBean(String beanId);
5 }
View Code

ClassPathXmlApplicationContext

[Java] SpringDemo第2张[Java] SpringDemo第3张
 1 package di;
 2 
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 import java.util.List;
 6 
 7 public class ClassPathXmlApplicationContext implements ApplicationContext{
 8     private BeansFactory beansFactory;
 9     private BeanConfigParser beanConfigParser;
10 
11     public ClassPathXmlApplicationContext(String configLocation) {
12         this.beansFactory = new BeansFactory();
13         this.beanConfigParser = new XmlBeanConfigParser();
14         loadBeanDefinitions(configLocation);
15     }
16 
17     private void loadBeanDefinitions(String configLocation) {
18         InputStream in = null;
19         try {
20             in = this.getClass().getResourceAsStream(configLocation);
21             if (in == null) {
22                 throw new RuntimeException(("Can not find config file: " + configLocation));
23             }
24 
25             List<BeanDefinition> beanDefinitions = beanConfigParser.parse(in);
26             beansFactory.addBeanDefinitions(beanDefinitions);
27         } finally {
28             if(in != null) {
29                 try {
30                     in.close();
31                 } catch (IOException e) {
32                 }
33             }
34         }
35     }
36 
37     @Override
38     public Object getBean(String beanId) {
39         return beansFactory.getBean(beanId);
40     }
41 }
View Code

BeanConfigParser

[Java] SpringDemo第2张[Java] SpringDemo第3张
1 package di;
2 
3 import java.io.InputStream;
4 import java.util.List;
5 
6 public interface BeanConfigParser {
7     List<BeanDefinition> parse(InputStream inputStream);
8 }
View Code

XmlBeanConfigParser

[Java] SpringDemo第2张[Java] SpringDemo第3张
 1 package di;
 2 
 3 import org.w3c.dom.Document;
 4 import org.w3c.dom.Element;
 5 import org.w3c.dom.Node;
 6 import org.w3c.dom.NodeList;
 7 
 8 import javax.xml.parsers.DocumentBuilder;
 9 import javax.xml.parsers.DocumentBuilderFactory;
10 import java.io.InputStream;
11 import java.util.ArrayList;
12 import java.util.List;
13 
14 public class XmlBeanConfigParser implements BeanConfigParser{
15 
16     @Override
17     public List<BeanDefinition> parse(InputStream inputStream) {
18         List beanDefinitions = new ArrayList<>();
19 
20         try {
21             DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
22             DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
23             Document doc = documentBuilder.parse(inputStream);
24 
25             // TODO: read it later, 关于 xml 为什么需要 normalize 一下
26             //optional, but recommended
27             //read this - http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work
28             doc.getDocumentElement().normalize();
29 
30             NodeList beanList = doc.getElementsByTagName("bean");
31 
32             for (int i = 0; i < beanList.getLength(); i++) {
33                 Node node = beanList.item(i);
34                 if (node.getNodeType() != Node.ELEMENT_NODE) continue;
35 
36                 Element element = (Element) node;
37                 BeanDefinition beanDefinition = new BeanDefinition(
38                         element.getAttribute("id"),
39                         element.getAttribute("class")
40                 );
41                 if (element.getAttribute("scope").equals("singleton")) {
42                     beanDefinition.setScope(BeanDefinition.Scope.SINGLETON);
43                 }
44                 if (element.getAttribute("lazy-init").equals("true")) {
45                     beanDefinition.setLazyInit(true);
46                 }
47                 loadConstructorArgs(
48                         element.getElementsByTagName("constructor-arg"),
49                         beanDefinition
50                 );
51 
52                 beanDefinitions.add(beanDefinition);
53              }
54         } catch (Exception e) {
55             e.printStackTrace();
56         }
57 
58         return beanDefinitions;
59     }
60 
61     public void loadConstructorArgs(NodeList nodes, BeanDefinition beanDefinition) {
62         for (int i = 0; i < nodes.getLength(); i++) {
63             Node node = nodes.item(i);
64             if (node.getNodeType() != Node.ELEMENT_NODE) continue;
65             Element element = (Element) node;
66 
67             BeanDefinition.ConstructorArg constructorArg = null;
68             if (!element.getAttribute("type").isEmpty()) {
69                 constructorArg = new BeanDefinition.ConstructorArg.Builder()
70                         .setArg(element.getAttribute("value"))
71                         .setType(String.class)
72                         .build();
73             }
74 
75             if (!element.getAttribute("ref").isEmpty()) {
76                 constructorArg = new BeanDefinition.ConstructorArg.Builder()
77                         .setRef(true)
78                         .setArg(element.getAttribute("ref"))
79                         .build();
80             }
81 
82             beanDefinition.addConstructorArg(constructorArg);
83         }
84     }
85 }
View Code

BeanDefinition

[Java] SpringDemo第2张[Java] SpringDemo第3张
  1 package di;
  2 
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 
  6 public class BeanDefinition {
  7     private String id;
  8     private String className;
  9     private List<ConstructorArg> constructorArgs = new ArrayList();
 10     private Scope scope = Scope.PROTOTYPE;
 11     private boolean lazyInit = false;
 12 
 13     public BeanDefinition(String id, String className) {
 14         this.id = id;
 15         this.className = className;
 16     }
 17 
 18     public Boolean isSingleton() {
 19         return scope.equals(Scope.SINGLETON);
 20     }
 21 
 22     public boolean isLazyInit() {
 23         return lazyInit;
 24     }
 25 
 26     public void addConstructorArg(ConstructorArg constructorArg) {
 27         this.constructorArgs.add(constructorArg);
 28     }
 29 
 30     // getter && setter
 31     public void setScope(Scope scope) {
 32         this.scope = scope;
 33     }
 34     public void setLazyInit(Boolean lazyInit) {
 35         this.lazyInit = lazyInit;
 36     }
 37     public String getId() {
 38         return id;
 39     }
 40     public String getClassName() {
 41         return className;
 42     }
 43     public List<ConstructorArg> getConstructorArgs() {
 44         return constructorArgs;
 45     }
 46 
 47 
 48     // Static Below
 49     public static enum Scope {
 50         SINGLETON,
 51         PROTOTYPE
 52     }
 53 
 54     public static class ConstructorArg {
 55         private boolean isRef;
 56         private Class type;
 57         private Object arg;
 58 
 59         /**
 60          * 内部静态类,可以访问私有构造函数?
 61          */
 62         private ConstructorArg(Builder builder) {
 63             this.isRef = builder.getIsRef();
 64             this.type = builder.getType();
 65             this.arg = builder.getArg();
 66         }
 67 
 68         public static class Builder {
 69             private boolean isRef = false;
 70             private Class type;
 71             private Object arg;
 72 
 73             public Builder setRef(Boolean isRef) {
 74                 this.isRef = isRef;
 75                 return this;
 76             }
 77 
 78             public Builder setType(Class type) {
 79                 this.type = type;
 80                 return this;
 81             }
 82 
 83             public Builder setArg(Object arg) {
 84                 this.arg = arg;
 85                 return this;
 86             }
 87 
 88             public ConstructorArg build() {
 89                 if (this.isRef) {
 90                     if (this.type != null) {
 91                         throw new IllegalArgumentException("当参数为引用类型时,无需设置 type 参数");
 92                     }
 93 
 94                     // null 是 string 实例妈?
 95                     if (!(arg instanceof String)) {
 96                         throw new IllegalArgumentException("请设置引用 ID");
 97                     }
 98                 } else {
 99                     if (this.type == null || this.arg == null) {
100                         throw new IllegalArgumentException("当参数为非引用类型时,type 和 arg 参数必填");
101                     }
102                 }
103 
104                 return new ConstructorArg(this);
105             }
106 
107             // Getter
108             public boolean getIsRef() {
109                 return isRef;
110             }
111 
112             public Class getType() {
113                 return type;
114             }
115 
116             public Object getArg() {
117                 return arg;
118             }
119         }
120 
121         public boolean isRef() {
122             return isRef;
123         }
124         public Class getType() {
125             return type;
126         }
127         public Object getArg() {
128             return arg;
129         }
130     }
131 }
View Code

BeansFactory

[Java] SpringDemo第2张[Java] SpringDemo第3张
 1 package di;
 2 
 3 import java.lang.reflect.InvocationTargetException;
 4 import java.util.List;
 5 import java.util.concurrent.ConcurrentHashMap;
 6 
 7 public class BeansFactory {
 8     private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
 9     private ConcurrentHashMap<String, BeanDefinition> beanDefinations = new ConcurrentHashMap<>();
10 
11     public void addBeanDefinitions(List<BeanDefinition> beanDefinitionList) {
12         for (BeanDefinition beanDefinition: beanDefinitionList) {
13             this.beanDefinations.putIfAbsent(beanDefinition.getId(), beanDefinition);
14         }
15 
16         for (BeanDefinition beanDefinition : beanDefinitionList) {
17             if (beanDefinition.isLazyInit() == false && beanDefinition.isSingleton()) {
18                 createBean(beanDefinition);
19             }
20         }
21     }
22 
23     public Object getBean(String beanId) {
24         BeanDefinition beanDefinition = beanDefinations.get(beanId);
25         if (beanDefinition == null) {
26             throw new NoSuchBeanDefinitionException("Bean is not defined: " + beanId);
27         }
28 
29         return createBean(beanDefinition);
30     }
31 
32     protected Object createBean(BeanDefinition beanDefinition) {
33         if (beanDefinition.isSingleton() && singletonObjects.containsKey(beanDefinition.getId())) {
34             return singletonObjects.get(beanDefinition.getId());
35         }
36 
37         Object bean = null;
38         try {
39             Class beanClass = Class.forName(beanDefinition.getClassName());
40             List<BeanDefinition.ConstructorArg> args = beanDefinition.getConstructorArgs();
41             if (args.isEmpty()) {
42                 bean = beanClass.newInstance();
43             } else {
44                 Class[] argClasses = new Class[args.size()];
45                 Object[] argObjects = new Object[args.size()];
46                 for (int i = 0; i < args.size(); i++) {
47                     BeanDefinition.ConstructorArg arg = args.get(i);
48                     if (!arg.isRef()) {
49                         argClasses[i] = arg.getType();
50                         argObjects[i] = arg.getArg();
51                     } else {
52                         BeanDefinition refBeanDefinition = beanDefinations.get(arg.getArg());
53                         if (refBeanDefinition == null) {
54                             throw new NoSuchBeanDefinitionException("Bean is not defined: " + arg.getArg());
55                         }
56                         argObjects[i] = createBean(refBeanDefinition);
57                         argClasses[i] = argObjects[i].getClass();
58                     }
59                 }
60 
61                 bean = beanClass.getConstructor(argClasses).newInstance(argObjects);
62             }
63         } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
64             e.printStackTrace();
65         }
66 
67         if (bean != null && beanDefinition.isSingleton()) {
68             singletonObjects.putIfAbsent(beanDefinition.getId(), bean);
69             return singletonObjects.get(beanDefinition.getId());
70         }
71 
72         return bean;
73     }
74 }
View Code

RateLimiter

[Java] SpringDemo第2张[Java] SpringDemo第3张
 1 package di;
 2 
 3 public class RateLimiter {
 4     private RedisCounter redisCounter;
 5     public RateLimiter(RedisCounter redisCounter) {
 6         this.redisCounter = redisCounter;
 7     }
 8     public boolean isValid() {
 9         this.redisCounter.increamentAndGet();
10         return true;
11     }
12 }
View Code

RedisCounter

[Java] SpringDemo第2张[Java] SpringDemo第3张
 1 package di;
 2 
 3 public class RedisCounter {
 4     private String ipAddress;
 5     private String port;
 6     public RedisCounter(String ipAddress, String port) {
 7         this.ipAddress = ipAddress;
 8         this.port = port;
 9     }
10 
11     public int increamentAndGet() {
12         System.out.println("Connect to " + this.ipAddress + ":" + this.port);
13         return 10;
14     }
15 }
View Code

SpringDemo

[Java] SpringDemo第2张[Java] SpringDemo第3张
 1 package di;
 2 
 3 public class DiDemo {
 4     public static void main(String[] args) {
 5         ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
 6         RateLimiter rateLimiter = (RateLimiter) applicationContext.getBean("rateLimiter");
 7         Boolean isValid = rateLimiter.isValid();
 8         System.out.println("RateLimiter call isValid method, result: " + isValid);
 9     }
10 }
View Code

beans.xml

[Java] SpringDemo第2张[Java] SpringDemo第3张
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans>
 3     <bean id="rateLimiter" class="di.RateLimiter">
 4         <constructor-arg ref="redisCounter"></constructor-arg>
 5     </bean>
 6     
 7     <bean id="redisCounter" class="di.RedisCounter">
 8         <constructor-arg type="String" value="127.0.0.1"></constructor-arg>
 9         <constructor-arg type="int" value="1234" ></constructor-arg>
10     </bean>
11 </beans>
View Code

[Java] SpringDemo第22张

AOP(待补充)

思想

  • 业务代码,日志/安全/事务/性能代码
  • 装饰器模式
  • 切面

实现

  • xml文件
  • 注解

事务(待补充)

相关概念

Java bean

  • 一个java bean 就是一个普通的java 类, 需满足以下要求
    • 需要是public 的, 有个无参数的构造函数
    • 属性是private 的, 通过setXXX()和getXXX()来访问
    • 支持“事件”, 例如addXXXXListener(XXXEvent e),可以是Click事件,Keyboard事件,或自定义事件 
    • 提供自省/反射机制, 能在运行时查看java bean 的各种信息
    • 可以序列化, 即可以把bean的状态保存的硬盘上, 以便以后来恢复

参考

Java bean

https://www.zhihu.com/question/19773379

ConcurrentHashMap

https://blog.csdn.net/weixin_44460333/article/details/86770169

免责声明:文章转载自《[Java] SpringDemo》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇sshd_config OpenSSH SSH 进程配置文件配置说明如何在微信企业号中使用简道云下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C# 对象与JSON串互相转换

using System;using System.IO;using System.Text;using Newtonsoft.Json;namespace OfflineAcceptControl.UCTools{ public class JsonTools { // 从一个对象信息生成Json串 public...

java在图片上添加文字

业务需求要在图片上添加水印。下面粘出代码供自己和大家分享 packagecom.pro.drawTextOnImg; importjava.awt.Color; importjava.awt.Font; importjava.awt.FontMetrics; importjava.awt.Graphics2D; importjava.awt.Im...

SpringMVC基础知识

SpringMVC SpringMVC简介: SpringMVC是一个表示层框架,搭建真实环境 SpringMVC的使用方法:注解和配置。(注解为主) SpringMVC是Spring3.x的一个模块,其实就是用MVC提供的表示层框架。 SpringMVC对视图组件没有必然要求,不一定要使用jsp,struts1,struts2规定了只能用jsp。 Spr...

Java生成UUID

转自:http://www.cnblogs.com/hellojava/archive/2012/12/03/2799953.html UUID含义是通用唯一识别码(Universally Unique Identifier),这是一个软件建构的标准,也是被开源软件基金会 (Open Software Foundation, OSF) 的组织应用在分布式计...

JAVA多线程提高八:线程锁技术

前面我们讲到了synchronized;那么这节就来将lock的功效。 一、locks相关类 锁相关的类都在包java.util.concurrent.locks下,有以下类和接口: |---AbstractOwnableSynchronizer |---AbstractQueuedLongSynchronizer |---AbstractQueued...

string.format()

Lua提供了string.format()函数来生成具有特定格式的字符串, 函数的第一个参数是格式(formatstring), 之后是对应格式中每个代号的各种数据. 由于格式字符串的存在, 使得产生的长字符串可读性大大提高了. 这个函数的格式很像C语言中的printf().函数string.format在用来对字符串进行格式化的时候,特别是字符串输出,是...