• [Java] SpringDemo


    IoC/DI

    功能

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

    组成

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

    过程

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

    代码

    ApplicationContext

    1 package di;
    2 
    3 public interface ApplicationContext {
    4     Object getBean(String beanId);
    5 }
    View Code

    ClassPathXmlApplicationContext

     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

    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

     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

      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

     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

     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

     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

     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

     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

    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

  • 相关阅读:
    Django_redis_session
    python_redis操作
    Django_url反向解析
    Django_分页
    Django_cookie与sesstion
    Django 自定义错误页面 403 404...
    Django_设置静态文件、上传文件
    Django设置子路由
    nginx、uwsgi
    CentOS安装MySQL
  • 原文地址:https://www.cnblogs.com/cxc1357/p/12987937.html
Copyright © 2020-2023  润新知