首页 文章 精选 留言 我的

精选列表

搜索[数据库设计],共10000篇文章
优秀的个人博客,低调大师

设计模式学习---单例模式

单例模式---对于整个系统只需要一个实体就能完成工作的情况下,我们系统只需要一个实体并且保证只有一个实例,避免造成资源浪费 1.懒汉 懒汉模式是在需要用到该实例的时候才进行实例化 优点:节约资源,在需要用到该实例的时候才初始化 缺点:线程非安全,并发访问情况下,有可能多次实例化,并且每次实例化都覆盖上一次的实例 public class Singleton { private static Singleton SINGLETON; private Singleton(){} public static Singleton getInstance(){ if(Singleton.SINGLETON == null); Singleton.SINGLETON = new Singleton(); return SINGLETON; } } 2.饿汉 饿汉单例模式在类加载的时候就实例化 优点:安全,不存在并发创建多实例问题 缺点:容易造成资源浪费,一直占用着资源且无法回收 public class Singleton { private static final Singleton SINGLETON = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return SINGLETON; } } 3.懒汉模式(方法加锁) 这种模式在获取实例的时候添加synchronize同步锁能避免多并发情况下造成创建多实例问题 优点:具有懒汉模式的节约资源优点,且方法加锁情况下避免了多并发创建多次实例的情况 确定:方法锁消耗性能比较大,必须是第一访问完整个方法才到第二次访问进入 public class Singleton { private static Singleton SINGLETON; private Singleton(){} public synchronized static Singleton getInstance(){ if(Singleton.SINGLETON == null); Singleton.SINGLETON = new Singleton(); return SINGLETON; } } 4.双重锁校验(推荐) 双重锁校验是优化了方发锁的方式而来,优化啊了多并发情况下性能低下的结果 优点:保证了线程安全情况下,节约资源且访问性能高 public class Singleton { private static Singleton SINGLETON; private Singleton(){} public static Singleton getInstance(){ if(Singleton.SINGLETON == null){ synchronized (Singleton.class) { if(Singleton.SINGLETON == null) { Singleton.SINGLETON = new Singleton(); } } } return SINGLETON; } } 进入方法体之后首先判断了实例是否存在,如果存在,则直接返回实例,否则加锁执行多一次判断,如果为null再实例化。因为第一次判断和加锁之间,对象可能已经实例化,所以加锁之后再判断一次,避免多次创建。但是这种方式还有点缺陷,synchronized关键字可以保证多线程情况下同步问题,如果是多核计算机(现在绝大部分都是多核计算机)情况下,还会有一个指令重排的问题所以我们需要用volatile 来修饰SINGLETON,最后改造成下面代码 public class Singleton { private volatile static Singleton SINGLETON; private Singleton(){} public static Singleton getInstance(){ if(Singleton.SINGLETON == null){ synchronized (Singleton.class) { if(Singleton.SINGLETON == null) { Singleton.SINGLETON = new Singleton(); } } } return SINGLETON; } } 5.静态内部类 静态内部类是在调用的时候才会进行加载,是懒汉模式另外一种实现方式 public class Singleton { private Singleton(){} public static Singleton getInstance(){ return Instance.singleton; } private static class Instance{ private static final Singleton singleton = new Singleton(); } } 6.枚举 枚举为最优的单例模式实现方案,因为可以防反射暴力创建对象,也可以避免序列化问题,下面先放了一个简单的例子, public enum SingletonEnum { SINGLETON; private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public static SingletonEnum getInstance(){ return SINGLETON; } } 看一下使用方式 public static void main(String[] args) { SingletonEnum.SINGLETON.setName("name1"); System.out.println(SingletonEnum.SINGLETON.getName()); } 输出结果,由此可见SingletonEnum.SINGLETON 时调用的都是同一个实例 下面我们看看枚举类型防放射暴力创建实例 我们用之前静态内部类的那个代码来比较 public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { // 反射获取构造器 Constructor<Singleton> singletonConstructor = Singleton.class.getDeclaredConstructor(); // 通过构造器创建对象 Singleton singleton1 = singletonConstructor.newInstance(); // 通过我们单例获取实例的接口获取实例 Singleton singleton2 = Singleton.getInstance(); // 下面结果为false,证明是2个不一样的实例,甚至都不用调用构造器的 setAccessible() 就能成功新建一个实例 System.out.println(singleton1 == singleton2); } 接下来再看看枚举 public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { // 反射获取构造器 Constructor<SingletonEnum> singletonEnumConstructor = SingletonEnum.class.getDeclaredConstructor(); // 通过构造器创建对象 SingletonEnum singletonEnum1 = singletonEnumConstructor.newInstance(); // 获取单例 SingletonEnum singletonEnum2 = SingletonEnum.SINGLETON; // 下面结果为false,证明是2个不一样的实例,甚至都不用调用构造器的 setAccessible() 就能成功新建一个实例 System.out.println(singletonEnum1 == singletonEnum2); } 这时候报是报了个java.lang.NoSuchMethodException,原因是因为枚举类型没有无参构造 下面我们进入debug模式可以看到只有一个带一个String参数和一个int参数的构造方法 所以改造成 public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { // 反射获取构造器 Constructor<SingletonEnum> singletonEnumConstructor = SingletonEnum.class.getDeclaredConstructor(String.class,int.class); // 通过构造器创建对象 SingletonEnum singletonEnum1 = singletonEnumConstructor.newInstance("",1); // 获取单例 SingletonEnum singletonEnum2 = SingletonEnum.SINGLETON; // 下面结果为false,证明是2个不一样的实例,甚至都不用调用构造器的 setAccessible() 就能成功新建一个实例 System.out.println(singletonEnum1 == singletonEnum2); } 但是改过来之后报了个 java.lang.IllegalAccessException 非法访问异常 原因是如果实例化的对象是个枚举类型,就会抛出这个异常,这说明枚举类型天生就是单例的 public T newInstance(Object ... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { Class<?> caller = Reflection.getCallerClass(); checkAccess(caller, clazz, null, modifiers); } } if ((clazz.getModifiers() & Modifier.ENUM) != 0) throw new IllegalArgumentException("Cannot reflectively create enum objects"); ConstructorAccessor ca = constructorAccessor; // read volatile if (ca == null) { ca = acquireConstructorAccessor(); } @SuppressWarnings("unchecked") T inst = (T) ca.newInstance(initargs); return inst; } if ((clazz.getModifiers() & Modifier.ENUM) != 0) throw new IllegalArgumentException("Cannot reflectively create enum objects"); 序列化与反序列化,如果我们实体需要储存到程序以外的存储媒介,当再次获取时候,这个实例并非我们最开始的实例 序列化的时候实体类必须实现Serializable public class Singleton implements Serializable{} public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException { // 通过获取实例接口获取实例 Singleton singleton1 = Singleton.getInstance(); // 创建输出流并且输出到文件 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\singleton\\singleton.txt")); oos.writeObject(singleton1); // 创建输入流并且反序列化实例 ObjectInputStream ios = new ObjectInputStream(new FileInputStream("D:\\singleton\\singleton.txt")); Singleton singleton2 = (Singleton) ios.readObject(); oos.close(); ios.close(); System.out.println(singleton1 == singleton2); } 序列化前后的对象结果对比,不是同一个实例 再看看枚举类型 public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException { SingletonEnum singletonEnum1 = SingletonEnum.SINGLETON; // 创建输出流并且输出到文件 ObjectOutputStream oosE = new ObjectOutputStream(new FileOutputStream("D:\\singleton\\singletonE.txt")); oosE.writeObject(singletonEnum1); // 创建输入流并且反序列化实例 ObjectInputStream iosE = new ObjectInputStream(new FileInputStream("D:\\singleton\\singletonE.txt")); SingletonEnum singletonEnum2 = (SingletonEnum) iosE.readObject(); oosE.close(); iosE.close(); System.out.println(singletonEnum1 == singletonEnum2); } 序列化前后的对象是一致的,没有被破坏 所以单例的最优方案是枚举,其他方法都会因为反射或者序列化破坏了整个系统只有一个实例的原则,当然根据业务要求选择一种比较合适目前开发团队的方案也很重要

优秀的个人博客,低调大师

SAP CRM Relationship API设计原理

Unlike settype, relationship does not have a dedicated read function module maintained in its metadata table. Instead, the generic read function module COM_IL_DB_READ is used. Below is a simple explanation about each parameter of FM COM_IL_DB_READ, using read on relationship PRDCPN for example. IV_RELTYPE PRDCPN - relationship name IV_ATTR_TYPE COMT_IL_PRDCPN_ATTR_TYPE - contains relationship specific business data, in this example, the customer product id is stored in field PRID_VENDOR IT_LINK_IDENTS sourceguid or destiguid contains product guid. This will be used by the generic read API to select against DB table using OPEN SQL. The exporting parameter: ET_INTERLINKAGE - relationship header data - generic data ET_IL_ATTR Relationship specific data, in this example, PRID_VENDOR, stores the detail value. Approach1 If we can enhance COM_IL_DB_READ, we then redirect the read from CRM relationship storage table to S4 relationship storage table.Since it is not allowed to enhance SAP_ABA function module, we have to consider CDS view redirect.Further research is needed here: compare the structure of both storage table in CRM and S4 and evaluate whether view direct is feasible or not. Approach2 Since we can only make changes on BBPCRM, we have to copy the whole implementation which are in SAP_ABAP listed below into new function & subroutine, make needed changes ( table redirect ) and let FORM UI_GETDETAIL call those new implementations. This approach takes huge effort. 本文来自云栖社区合作伙伴“汪子熙”,了解相关信息可以关注微信公众号"汪子熙"。

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册