支撑Java框架的基础技术:泛型,反射,动态代理,cglib
以Spring为例要想看明白他的源码需要彻底理解Java的一些基础技术泛型,反射同时对于一些高级技术例如动态代理,cglib和字节码技术也需要掌握,下面就按章节来一一说清楚这些技术的核心部分,最后手写一个简单的Spring框架。
一.静态代码块和非静态代码块以及构造函数的调用顺序
静态代码块:https://stackoverflow.com/questions/2420389/static-initialization-blocks
每次构造类的实例时都会调用它。在静态块只被调用一次,当类本身初始化,无论你如何创建该类型的许多对象。
例子二:
下面这个例子用于演示完整的代码调用顺序。
先看父类:
public class Parent {static String name = "hello";//非静态代码块{System.out.println("1");}//静态代码块static {System.out.println("2");}public Parent() {System.out.println("3");}
}
再看子类:
public class Child extends Parent {static String childName = "hello";{System.out.println("4");}static {System.out.println("5");}public Child() {System.out.println("6");}
}
调用测试的主函数:
public class StaticCodeBlockOrderTest {public static void main(String[] args) {new Child();}
}
输出:
对象的初始化顺序:
首先执行父类静态的内容,父类静态的内容执行完毕后,接着去执行子类的静态的内容,当子类的静态内容执行完毕之后,再去看父类有没有非静态代码块,
如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕,接着执行父类的构造方法;父类的构造方法执行完毕之后,它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块。
子类的非静态代码块执行完毕再去执行子类的构造方法。
参考:java中静态代码块的用法 static用法详解
静态代码块的应用场景:
需要一个Util类,需要系统初始化的时候就初始化一个hashMap,部分代码省略以...代替
private static Map<String, List<String>> smap = new HashMap<String, List<String>>();static {for (int i = 0; i < k; i++) {List<String> ls = new ArrayList<String>();ls.add(...);ls.add(...);smap.put(..., ls);}}
这个一样的用法:Map的静态赋值
二.泛型:
这个老外的视频讲的很好《Java Generics》
E - Element (在集合中使用,因为集合中存放的是元素)
T - Type(Java 类)
K - Key(键)
V - Value(值)
N - Number(数值类型)
? - 表示不确定的java类型
1.泛型类
https://blog.csdn.net/weixin_43819113/article/details/91042598
https://www.cnblogs.com/coprince/p/8603492.html
泛型类有普通方法返回T,和泛型方法<T> T。
2.泛型方法
泛型方法可以不用是泛型类 ,有泛型参数需要才是泛型方法返回值之前需要泛型参数
static 后的<E>是泛型声明,这样才可以在这个方法参数和方法体用泛型
static <E>后的Set<E>是返回值
泛型类:
不用泛型需要强转:
输出:
[123, 456, 789]
[123, 456, 789, 123, 456, 789]
[123, 456, 789]
3.泛型 Class<T>和Class<?>的差异
public class Box<T> {private T t;public Box(){}public Box(T data){this.t=data;}public T getT() {return t;}public void setT(T t) {this.t = t;}
}
调用
public static void main(String[] args) {Box<String> s=new Box<String>("abc");Box<Integer> i=new Box<Integer>(123);System.out.println("s class:" + s.getClass());System.out.println("i class:" + i.getClass());System.out.println(s.getClass() == i.getClass());
}
输出
为什么有Class<T>还需要Class<?>呢?
其实看这个就明白了
在其他类中例如这个Test里,你可以定义
public static void getData(Box<String> data){System.out.println("data :" + data.getT());}
也可以定义
public static void getData(Box<Integer> data){System.out.println("data :" + data.getT());}
但是你要是同时定义这2个就会报错
名称冲突: getData(Box<Integer>)和getData(Box<String>)具有相同疑符
使用通配符?就可以解决这个问题
public class TestMain {public static void main(String[] args) {Box<String> s=new Box<String>("abc");Box<Integer> i=new Box<Integer>(123);System.out.println("s class:" + s.getClass());System.out.println("i class:" + i.getClass());System.out.println(s.getClass() == i.getClass());getData(s);getData(i);}public static void getData(Box<?> data){System.out.println("data :" + data.getT());}
}
参考:
Java总结篇系列:Java泛型
java中的泛型总结
再来看看Class<?>的用处
public class TestMain {public static void main(String[] args) {Box<String> s=new Box<String>("http://blog.csdn.net/unix21");Box<Integer> i=new Box<Integer>(123);System.out.println("s class:" + s.getClass());System.out.println("i class:" + i.getClass());System.out.println(s.getClass() == i.getClass());getData(Box.class);}public static void getData(Class<?> clz){try {System.out.println(clz);System.out.println("clz.hashCode():" + clz.hashCode());Object o=clz.newInstance();o.hashCode();System.out.println("o.hashCode():" + o.hashCode());} catch (Exception e) { System.out.println(e); } }
}
((Box)clz).getT();会报错:
不能将 "class java.lang.Class (no class loader)" 的实例强制转换为 "class test.Box (loaded by instance of sun.misc.Launcher$AppClassLoader(id=144))" 的实例
说明还没有class loader
((Box)o).getT();就已经实例化了。
4.Object类型
定义的所有类默认都是子类,所有的类都是以标准类Object为基础,Object类型的变量可以存储指向任意类类型对象的索引。
当要为一个方法来处理未知类型的对象时,这很有用。
//存储的地方HashMap<String , Object> map = new HashMap<String , Object>();User u1=new User();u1.setId(1);u1.setName("ww1");//Object可以塞任意类型map.put("user",u1);User u=(User)map.get("user");response.getWriter().println("Hello Servlet >>>"+u.getName());String clazz ="com.w1.User"; //bean.getAttributeValue("class");try {//反射Object o = Class.forName(clazz).newInstance();map.put("user2",o);User u2=(User)map.get("user2");u2.setName("ww223");response.getWriter().println("Hello Servlet >>>"+u2.getName());} catch (Exception e) {e.printStackTrace();}
三.反射
反射可以参考本人的反射深入专贴:深入浅出Java反射原理和使用场景
这里限于篇幅只罗列一点精华内容。
类名.class, class.forName(), getClass()区别
1:Class cl=A.class;
JVM将使用类A的类装载器, 将类A装入内存(前提是:类A还没有装入内存),不对类A做类的初始化工作.返回类A的Class的对象。
2:Class cl=对象引用o.getClass();
返回引用o运行时真正所指的对象(因为:子对象的引用可能会赋给父对象的引用变量中)所属的类的Class的对象 。
3:Class.forName("类名");
.装入类A,并做类的初始化
.getClass()是动态的,其余是静态的。
.class和class.forName()只能返回类内field的默认值,getClass可以返回当前对象中field的最新值
Class.forName() 返回的是一个类,.newInstance() 后才创建一个对象,Class.forName()的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的。
public class Person {private String name = "Alfira";public void getName() {System.out.println(name);}public void setName(String name, int a) {this.name = name + a;}
}
private static void show(String name) {try {// JVM将使用类A的类装载器,将类A装入内存(前提是:类A还没有装入内存),不对类A做类的初始化工作Class classtype3 = Person.class;// 获得classtype中的方法Method getMethod3 = classtype3.getMethod("getName", new Class[] {});Class[] parameterTypes3 = { String.class, int.class };Method setMethod3 = classtype3.getMethod("setName", parameterTypes3);// 实例化对象,因为这一句才会输出“静态初始化”以及“初始化”Object obj3 = classtype3.newInstance();// 通过实例化后的对象调用方法getMethod3.invoke(obj3); // 获取默认值setMethod3.invoke(obj3, "Setting new ", 3); // 设置getMethod3.invoke(obj3); // 获取最新System.out.println("----------------");// 返回运行时真正所指的对象Person p = new Person();Class classtype = p.getClass();// Class.forName(name);// 获得classtype中的方法Method getMethod = classtype.getMethod("getName", new Class[] {});Class[] parameterTypes = { String.class, int.class };Method setMethod = classtype.getMethod("setName", parameterTypes);getMethod.invoke(p);// 获取默认值setMethod.invoke(p, "Setting new ", 1); // 设置getMethod.invoke(p);// 获取最新System.out.println("----------------");// 装入类,并做类的初始化Class classtype2 = Class.forName(name);// 获得classtype中的方法Method getMethod2 = classtype2.getMethod("getName", new Class[] {});Class[] parameterTypes2 = { String.class, int.class };Method setMethod2 = classtype2.getMethod("setName", parameterTypes2);// 实例化对象Object obj2 = classtype2.newInstance();// 通过实例化后的对象调用方法getMethod2.invoke(obj2); // 获取默认值setMethod2.invoke(obj2, "Setting new ", 2); // 设置getMethod2.invoke(obj2); // 获取最新System.out.println("----------------");} catch (Exception e) {System.out.println(e);}}
调用
show("com.Person");
参考此文:http://www.cnblogs.com/feiyun126/archive/2013/08/01/3229492.html
http://blog.163.com/granite8@126/blog/static/853746082008610102657141/
四.JDK动态代理和CGLIB动态代理的区别
https://stackoverflow.com/questions/10664182/what-is-the-difference-between-jdk-dynamic-proxy-and-cglib
JDK动态代理只能通过接口代理(因此您的目标类需要实现一个接口,然后由代理类实现)。
CGLIB(和javassist)可以通过子类创建代理。在这种情况下,代理成为目标类的子类。不需要接口。
所以Java动态代理可以代理:public class Foo implements iFoo
CGLIB可以代理的地方:public class Foo
我应该提一下,因为javassist和CGLIB通过子类化使用代理,这就是你在使用依赖于它的框架时不能声明 final方法或使类 final的原因。这将阻止这些库允许子类化您的类并覆盖您的方法。
还应该注意的是,CGLib子类创建需要足够了解超类,以便能够使用正确的args调用正确的构造函数。与基于接口的代理不同,它不关心构造函数。这使得使用CGLib代理比JDK代理更少“自动”。另一个区别在于“堆叠”成本。JDK代理总是在每次调用时产生额外的堆栈帧,而CGLib可能不会花费任何额外的堆栈帧。随着应用程序越复杂,这变得越来越相关(因为堆栈越大,内存线程消耗越多)。
CGLIB不能代理 final方法,但不会抛出异常gist.github.com/mhewedy/7345403cfa52e6f47563f8a204ec0e80 - Muhammad Hewedy
使用CGLIB库动态创建代理
CGLIB库是ASM之上的高级层。它对代理不实现接口的类非常有用。本质上,它动态生成一个子类来覆盖代理类的非final方法,并连接回调用户定义的拦截器的钩子。它比JDK动态代理方法更快。
CGLIB是一个功能强大的高性能代码生成库。它是JDK动态代理的补充,因为它提供了不实现接口的代理类。在封面下,它使用ASM字节码操作框架。实质上,CGLIB动态生成一个子类来覆盖代理类的非final方法。它比使用Java反射的JDK动态代理方法更快。CGLIB不能使用任何最终方法代理最终类或类。对于一般情况,您使用JDK动态代理方法来创建代理。当接口不可用或性能问题时,CGLIB是一个很好的选择。
https://stackoverflow.com/questions/4411129/why-does-jdk-dynamic-proxy-only-work-with-interfaces
https://www.quora.com/In-Java-why-are-dynamic-proxies-only-allowed-to-proxy-interface-classes
我相信这个决定是在Java标准库中故意做出的,以支持接口而不是类继承。使用接口允许以不同方式引用相同的代理对象。
近年来,它也是Java最佳实践(或“类似Java”),它将对象称为接口类型而不是类,甚至是匿名类。匿名类通常用作扩展的基础 - 因此成语类C扩展BaseC实现InterfaceC。
对于更高级的用法,例如增强现有类,使用第三方库是可以接受的,因为这通常不是由最终用户开发人员完成的,而是由框架(例如Spring Framework)使用。
http://cliffmeyers.com/blog/2006/12/29/spring-aop-cglib-or-jdk-dynamic-proxies.html
即使您不是面向方面编程的忠实粉丝,如果您使用Spring框架的事务管理,您的应用程序将使用动态AOP代理,尽管是在幕后。Spring可以使用两种
不同的技术在运行时创建代理:CGLIB或JDK动态代理。
如果目标类实现了一个或多个接口,那么Spring将创建一个实现每个接口的JDK动态代理。如果目标类没有实现接口,Spring将使用CGLIB动态创建一个新类,它是目标类的子类(“extends”)。这导致了一个重要的区别:JDK动态代理无法转换为原始目标类,因为它只是一个动态代理,恰好实现了与目标相同的接口。如果在应用程序的模型中使用它们,这会“轻推”您对接口进行编程,因为通常会通过这些接口调用代理。
另一方面,如果模型中完全没有接口,Spring将创建CGLIB代理,可以像目标类本身一样对待或多或少。还有一种方式,迫使其在Spring文档详细介绍这两种情况下CGLIB代理的创作就在这里。
http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html
使用Java Reflection可以在运行时创建接口的动态实现。你这样做是使用这个类java.lang.reflect.Proxy
。这个类的名称就是我将这些动态接口实现称为动态代理的原因。动态代理可用于许多不同的目的,例如数据库连接和事务管理,用于单元测试的动态模拟对象,以及其他类似AOP的方法拦截目的。
已知动态代理至少用于以下目的:
- 数据库连接和事务管理
- 用于单元测试的动态模拟对象
- DI容器适应自定义工厂接口
- 类似AOP的方法拦截
https://www.logicbig.com/tutorials/core-java-tutorial/java-dynamic-proxies/runtime-interface-implementation.html
https://javax0.wordpress.com/2016/01/20/java-dynamic-proxy/
Java和CGLIB动态代理
下面举例演示使用方法:
public class SayHello {public void say(){System.out.println("hello everyone");}
}
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;public class CglibProxy implements MethodInterceptor {private Enhancer enhancer = new Enhancer();public Object getProxy(Class clazz) {//设置需要创建子类的类enhancer.setSuperclass(clazz);enhancer.setCallback(this);//通过字节码技术动态创建子类实例return enhancer.create();}//实现MethodInterceptor接口方法public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("前置代理");//通过代理类调用父类中的方法Object result = proxy.invokeSuper(obj, args);System.out.println("后置代理");return result;}
}
调用
CglibProxy proxy = new CglibProxy();//通过生成子类的方式创建代理类SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class);proxyImp.say();
CGLib动态代理原理及实现
Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)[转]
cglib动态代理介绍(一)
五.自己手写代码实现Spring的基本功能
需要说这个作者写到这一系列文章非常好【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)
代码:http://download.csdn.net/detail/jiuqiyuliang/8483981
这篇博文的目标是不仅形似Spring的IoC,而且要神似Spring的IoC,将对象的依赖关系进一步封装。
完整的项目结构
Dao接口和实现
public interface Dao {public void daoMethod();
}
public class Dao4MySqlImpl implements Dao {public void daoMethod(){System.out.println("Dao4MySqlImpl.daoMethod()");}
}
public class Dao4OracleImpl implements Dao {public void daoMethod(){System.out.println("Dao4OracleImpl.daoMethod()");}
}
Service接口和实现
public interface Service {public void serviceMethod();
}
public class ServiceImpl implements Service {private Dao dao; //依赖注入public void setDao(Dao dao) {this.dao= dao;}@Overridepublic void serviceMethod() {dao.daoMethod();}
}
public interface BeanFactory {Object getBean(String beanName);
}
import java.util.ArrayList;
import java.util.List;public class BeanDefinition {private String id;private String className;private List<PropertyDefinition> propertys = new ArrayList<PropertyDefinition>();public BeanDefinition(String id, String className) {this.id = id;this.className = className;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getClassName() {return className;}public void setClassName(String className) {this.className = className;}public List<PropertyDefinition> getPropertys() {return propertys;}public void setPropertys(List<PropertyDefinition> propertys) {this.propertys = propertys;}
}
核心容器
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 容器** @author liang**/
public class ClassPathXmlApplicationContext implements BeanFactory {// 用于存放Beanprivate List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();// 用于存放Bean的实例private Map<String, Object> sigletons =new HashMap<String, Object>();public ClassPathXmlApplicationContext(String fileName) {this.readXML(fileName);this.instanceBeans();this.injectObject();}/*** 为bean对象的属性注入值*/private void injectObject() {for (BeanDefinition beanDefinition :beanDefines) {Object bean = sigletons.get(beanDefinition.getId());if(bean != null){try {// 通过Introspector取得bean的定义信息,之后再取得属性的描述信息,返回一个数组PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();for(PropertyDefinition propertyDefinition:beanDefinition.getPropertys()){for(PropertyDescriptor properdesc: ps){if(propertyDefinition.getName().equals(properdesc.getName())){// 获取属性的setter方法,privateMethod setter = properdesc.getWriteMethod();if(setter != null){Object value = sigletons.get(propertyDefinition.getRef());// 允许访问私有方法setter.setAccessible(true);// 把引用对象注入到属性setter.invoke(bean, value);}break;}}}} catch (Exception e) {e.printStackTrace();}}}}/*** 完成bean的实例化*/private void instanceBeans() {for(BeanDefinition beanDefinition : beanDefines){try {if(beanDefinition.getClassName() != null && !"".equals(beanDefinition.getClassName().trim())){sigletons.put(beanDefinition.getId(),Class.forName(beanDefinition.getClassName()).newInstance() );}} catch (Exception e) {e.printStackTrace();}}}/*** 读取xml配置文件*/private void readXML(String fileName) {// 创建SAXBuilder对象SAXBuilder saxBuilder = new SAXBuilder();try {// 读取资源,获得document对象Document doc = saxBuilder.build(this.getClass().getClassLoader().getResourceAsStream(fileName));// 获取根元素Element rootEle = doc.getRootElement();// 从根元素获得所有的子元素,建立元素集合List listBean = XPath.selectNodes(rootEle, "/beans/bean");// 遍历根元素的子元素集合,扫描配置文件中的beanfor (int i = 0; i < listBean.size(); i++) {// 将根元素beans下的bean子元素作为一个新的子根元素Element elementBean = (Element) listBean.get(i);//获取id属性值String id = elementBean.getAttributeValue("id");//获取class属性值String clazz = elementBean.getAttributeValue("class");BeanDefinition beanDefine = new BeanDefinition(id,clazz);// 获取子根元素bean下的所有property子元素List listProperty = elementBean.getChildren("property");// 遍历子根元素的子元素集合(即遍历property元素)for (int j = 0; j < listProperty.size(); j++) {// 获取property元素Element elmentProperty = (Element)listProperty.get(j);// 获取name属性值String propertyName = elmentProperty.getAttributeValue("name");// 获取ref属性值String propertyref = elmentProperty.getAttributeValue("ref");PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName,propertyref);beanDefine.getPropertys().add(propertyDefinition);}// 将javabean添加到集合中beanDefines.add(beanDefine);}} catch (Exception e) {e.printStackTrace();}}/*** 获取bean实例*/@Overridepublic Object getBean(String beanName) {return this.sigletons.get(beanName);}
}
public class PropertyDefinition {private String name;private String ref;public PropertyDefinition(String name, String ref) {this.name = name;this.ref = ref;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getRef() {return ref;}public void setRef(String ref) {this.ref = ref;}}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans><bean id="dao" class="com.tgb.container.dao.impl.Dao4MySqlImpl" /><bean id="service" class="com.tgb.container.service.impl.ServiceImpl"><property name="dao" ref="dao"></property></bean>
</beans>
相关文章:
【CTF】实验吧 困在栅栏里的凯撒
题目先提到栅栏,再提到凯撒,按照顺序先栅栏解码,再凯撒解码。 一般密码的开头不是flag就是key或者ctf 所以选择“6栏”,在进行凯撒解码 在所有组合中,发现CTF即为flag
经典算法书籍推荐以及算法书排行【算法四库全书】
经典算法书籍推荐以及算法书排行【算法四库全书】 作者:霞落满天 https://linuxstyle.blog.csdn.net/ https://blog.csdn.net/21aspnet 行文方式:类似《四库全书》截取经典算法书目录和精华篇章 版权说明:本文于2019年5月5日首发于CS…
【CTF】实验吧 Fair-Play
它的标题就是题解的提示:Play-Fair Playfair解密算法首先将密钥填写在一个5*5的矩阵中(去Q留Z),矩阵中其它未用到的字母按顺序填在矩阵剩余位置中,根据替换矩阵由密文得到明文。 对密文解密规则如下: 1 若c…

【DAY23】JVM与反射的学习笔记
JVM:-----------------1.JVM: java virtual machine.2.class file *.class3.ClassLoader4.runtime data area运行时数据区。1.Method area : 方法区.(shared)供所有线程共享.2.heap(shared):供所有线程共享.3.java stack(栈区)独占的。4.native method stack(本地方法栈)独占5.…

BZOJ2281:[SDOI2011]黑白棋(博弈论,组合数学,DP)
Description 小A和小B又想到了一个新的游戏。这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色。最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同。小A可以移动白色棋子,小…

高性能微服务架构设计模式@霞落满天
高性能微服务架构设计模式 主讲:霞落满天 现在企业开发都是微服务架构,但是有很多问题,比如分布式定义,分布式的微服务怎么拆分,什么时候拆分,怎么做到高性能,中台怎么设计,读写分…

【数据结构】顺序栈的实现(C语言)
栈的基本概念及其描述 栈是一种特殊的线性表,规定它的插入运算和删除运算均在线性表的同一端进行,进行插入操作和删除操作的那一端称为栈顶,另一端称为栈底。 栈的插入操作和删除操作分别称为进栈和出栈。 FILO(First In Last …

iOS绘制图片与文字
2019独角兽企业重金招聘Python工程师标准>>> #####绘制图片与文字 #####1.绘制图片,直接代码说明 加载图片 #pragma mark - 小黄人 -(void) drawImage:(CGRect) rect{UIImage *image[UIImage imageNamed:"黄人"];//图片有可能显示不全…

php-fpm慢执行日志
vim /usr/local/php-fpm/etc/php-fpm.d/www.conf//加入如下内容request_slowlog_timeout 1slowlog /usr/local/php-fpm/var/log/www-slow.log 测试:/usr/local/php-fpm/sbin/php-fpm -t/etc/init.d/php-fpm reloadls ../../var/log/ //生成日志php-fpm.log www-sl…

spring springboot springcloud常用注解
SpringBootApplication 组合注解,用在启动类上,源码: Retention(RetentionPolicy.RUNTIME) SpringBootConfiguration EnableAutoConfiguration ComponentScan public interface SpringBootApplication SpringBootConfiguration Configurat…

解决eclipse ctrl+鼠标左键不能用
选择【Window】菜单 Preferences ——>General——>Editors——>Text Editors——>Hyperlinking 把勾都点上,然后确定KEY 值为 crtl

【数据结构】顺序队列的实现(C语言)
队列的基本概念及其描述 队列是一种特殊的线性表,它的特殊性在于队列的插入和删除操作分别在表的两端进行。 插入的那一端称为队尾,删除的那一端称为队首。队列的插入操作和删除操作分别称为进队和出队。 先进先出(First In First Out&…

ethereumjs/ethereumjs-vm-2-API文档
https://github.com/ethereumjs/ethereumjs-vm/blob/master/docs/index.md vm.runBlockchain Processes blocks and adds them to the blockchain 处理区块并将其添加到区块链中 Parameters输入参数 blockchain Blockchain A blockchain that to process 一个处理的区块链cb Fu…

qt 拖拽 修改大小(二)
最近项目需要实现windows下橡皮筋的效果,所以对此做了一些了解,特此记录。 首先windows系统是支持橡皮筋效果的,需要使用win32方 法:SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, showFullWindow, NULL, 0);showFullWindow是一个…

互联网大厂技术面试内幕@霞落满天
很多求职者往往并非因为技术不好,而是没有掌握面试的技巧导致不能把握机会,本课程的目的就是本课程先通过比较真实的好简历和不好的简历让大家明白自己的简历有哪些问题,事实上简历是大厂的敲门砖,非常重要,很多人得不…

【数据结构】顺序表的应用(1)(C语言)
问题: 1.将顺序表(a1,a2,…,an)重新排列以a1为界的两部分:a1前面的值均比a1小,a1后面的值均比a1大(这里假设数据元素的类型具有可比性,不妨设为整型)。 头文件与该头文件一样:【数据结构】顺序…

比特币寒冬中,你更应该关注企业区块链!
公众对区块链的认识也许限于比特币或以太坊,但很多却不知道 Hyperledger(超级账本)。Hyperledger Fabric,是由 IBM 带头发起的一个联盟链项目,2015 年末移交给 Linux 基金会,成为开源项目。Linux 基金会孵化…

JVM XMX设置多大比较好,Docke容器里该怎么设置JVM呢@无界编程
XMX是JVM的最大堆内存大小,XMS是JVM的初始堆内存大小。 不管是工作还是面试经常遇到一个问题就是XMX到底设置多大比较好? 网上的答案大多是说XMX和XMS设置为一样大,但是没有说到底XMX设置多大比较好。 如果设置为和操作系统一样大内存会怎么样? 这篇文章就带你搞清楚这…

【数据结构】顺序表的应用(2)(C语言)
问题: 2.有顺序表A和B,其元素均按从小到大的升序排列,编写一个算法,将它们合并成一个顺序表C,要求C的元素也按从小到大的升序排列。 头文件与该头文件一样:【数据结构】顺序表的实现(C语言&am…

OWA登录页面显示为英文而不是中文
-----提供AD\Exchange\Lync\Sharepoint\CRM\SC\O365等微软产品实施及外包,QQ:185426445.电话18666943750故障描述:WIN10操作系统使用IE登录OWA的时候,界面语言为英文,WIN10操作系统为中文系统,区域语言都是设置为中文&…

java B2B2C springmvc mybatis多租户电子商城系统-Spring Cloud Feign
1、什么是Feign? 愿意了解源码的朋友直接企鹅求求:二一四七七七五六三三 Feign 的英文表意为“假装,伪装,变形”, 是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求,而不用…

【数据结构】顺序表的应用(3)(C语言)
问题: 已知一个顺序表中的各节点值是从大到小有序的,设计一个算法,插入一个值为x的节点,使顺序表中的节点仍然是从小到大有序的。 头文件与该头文件一样:【数据结构】顺序表的实现(C语言) #i…

从源码和内核角度分析redis和nginx以及java NIO可以支持多大的并发
有人询问我网上一篇关于“redis为什么单线程这么快”的文章,我建议他不要看了,因为redis是单进程不是单线程,后面的意见不用看了,文章质量肯定不会很好,他也说了自己看了很久源码似乎还是有些云里雾里,所以我就给他分析了为什么redis这么快,这篇主要讲epoll的实现。 从…

背景图片等比缩放的写法background-size简写法
1、背景图片或图标也可像img一样给其宽高就能指定其缩放大小了。 比如一个实际宽高36*28的图标,要缩小一半引用进来的写法就是: background:rgba(0, 0, 0, 0) url("../images/report_icon2x.png") no-repeat scroll left center / 18px 14px; …

深入了解以太坊
正在看这篇文章的你,应该是一名被区块链技术所吸引的开发者或者极客。我相信你已经理解了区块链的技术原理,并急切地想要搞清楚这项技术将为你和你的开发技术栈带来怎样的影响。 如果你需要更基础的区块链技术介绍,可以阅读比特币和以太坊的白…

Netty和JDK源码来看Netty的NIO和JDK的NIO有什么不同
JDK底层提供了NIO实现,在Linux环境会调用内核epoll。 但是Netty通过JNI的方式提供了Native Socket Transport,为什么Netty要自己搞一套NIO呢? 这篇文章带你从jdk的源码和Netty的源码角度来分析为什么Netty要这么做。 JDK源码:openjdk-8u40 Netty源码:netty-4.1 1.先看J…
【数据结构】单链表的实现(C语言)
单链表是线性表链式储存的一种形式,其中的结点一般含有两个域,一个是存放数据信息的info域,另一个是指向该结点后继结点存放地址的指针next域。一个单链表必须要有一个首指针指向链表中的第一个结点。 单链表要掌握以下几种操作:…

《理解 OpenStack + Ceph》---来自-[爱.知识]-推荐
企业IT技术分享(2016-06-29)来自(QQ群:企业私有云平台实战 454544014-推荐)!理解 OpenStack Ceph (1):Ceph OpenStack 集群部署和配置http://www.cnblogs.com/sammyliu…

windows10 安装 mysql8.0.12 详解
【1】下载安装包 官网下载地址:https://downloads.mysql.com/archives/community/ 如下图所示: 下载完成,安装包为mysql-8.0.12-winx64.zip 【2】安装准备 (1)安装路径。拷贝安装包到任意路径,然后解压缩。…

IDEA常用和实用配置以及各种必要插件
主要是收集IDEA常用和不常用配置陆续更新 ------------------------ 启动项目配置 建议使用idea2021.1.3以上版本: ------------------------ maven没有设置自动导包,导致引用不到第三方依赖。 可以点maven的刷新按钮即可。 idea 设置gradle自动更…