OSGi介绍(五)两个bundle

普通jar包和osgi的Bundle包 开放服务网关协议 (Open Services Gateway Initiative),简称 OSGi,OSGI 为Java平台提供了动态模块化的特性,但是没有对Java底层实现如类库和Java虚拟机等修改.OSGi 的体系架构是基于插件式的软件结构,包括一个 OSGi 框架和一系列插件,在 OSGi中,插件称为 Bundle,Bundle 是以 jar 包形式存在的一个模块化物理单元,里面包含了代码,资源文件和元数据(metadata),并且 jar 包的物理边界也同时是运行时逻辑模块的封装边界... 阅读详情

(四)中提到的直接型改造法实际上和一个传统的java应用程序没有区别。因此客户的需求发生变化,通常是牵一发而动全身。
那么我们现在就看看如果在osgi framework中,用多个bundle来实现的效果吧。
我的想法是用两个bundle来配合实现“扶贫助手”的功能。一个bundle专门负责录入和显示纪录,一个bundle专门负责纪录的数据结构和对数据的处理,用时下时髦的说法就是使用了mvc,只是我的m和c放到了一起。
先看看mc的bundle实现代码片断:

package  com.wukong.test.family.control;
import  java.util. * ;
import  com.wukong.test.family.control.impl. * ;
public   interface  FamilyInfoDatabase  {
    public static class FamilyFactory {
        private static FamilyInfoDatabase database;
        public static FamilyInfoDatabase getDatabaseInstance(){
            if(database == null){
                database = new FamilyDatabase();
            }

            return database;
        }

    }

    public String[] getColumns();
    public Object getValueAt(int row, int column);
    public String[] getSortingFields();
    public int getRowCount();
    
    public void sort(String sortField) throws IllegalArgumentException;
    
    public void addEntry(List columns, List values) throws IllegalArgumentException;
    public void deleteEntry(String familyName);
    public void update(String familyName,List columns, List values)throws IllegalArgumentException;
}



这个interface是用来描述一个数据库所具备的基本功能。注意,这个interface被放到了package com.wukong.test.family.control中。
另外,这个interface还提供了一个内嵌类,用来专门提供一个工厂方法来产生唯一的一个数据库实例。
对于这个数据库的实现,代码片断如下(增加,删除和修改的代码都被省略了,只给出排序的代码):
package  com.wukong.test.family.model.impl;
public   class  FamilyInfoEntry  {
    private String familyName;
    private int population;
    private int incomePerYear;
    
    FamilyInfoEntry(String familyName,int population,int income){
        this.familyName = familyName;
        this.population = population;
        this.incomePerYear = income;
    }

    
    
    String getFamilyName() {
        return familyName;
    }

    int getIncomePerYear() {
        return incomePerYear;
    }

    int getPopulation() {
        return population;
    }

}


package  com.wukong.test.family.control.impl;
import  com.wukong.test.family.control.FamilyInfoDatabase;
import  java.util. * ;
public   class  FamilyDatabase  implements  FamilyInfoDatabase  {
    private LinkedList familyEntryList = new LinkedList();
    private Object[] sortedValues = null;
    public FamilyDatabase() {
        this.familyEntryList.add(new FamilyInfoEntry("Zhang",3,1200));
        this.familyEntryList.add(new FamilyInfoEntry("Li",6,1800));
        this.familyEntryList.add(new FamilyInfoEntry("Liu",4,1500));
        this.sortedValues = this.familyEntryList.toArray();
    }

    public String[] getColumns() {
        return new String[] { "Family Name", "Family Population", "Income" };
    }

    public Object getValueAt(int row, int column) {
        FamilyInfoEntry entry = (FamilyInfoEntry)this.sortedValues[row];
        switch (column) {
        case 0:
            return entry.getFamilyName();
        case 1:
            return new Integer(entry.getPopulation());
        case 2:
            return new Integer(entry.getIncomePerYear());
        default:
            throw new IllegalArgumentException("Invalid column index.");
        }

    }

    public String[] getSortingFields() {
        return new String[] { "FamilyName","Income" };
    }

    public int getRowCount() {
        return this.familyEntryList.size();
    }

    public void addEntry(List columns, List values)
            throws IllegalArgumentException {
    }

    public void deleteEntry(String familyName) {
    }

    public void update(String familyName, List columns, List values)
            throws IllegalArgumentException {
    }


    public void sort(String sortField) throws IllegalArgumentException{
        if(sortField.equals("FamilyName")){
            this.sortedValues = this.familyEntryList.toArray();
            Arrays.sort(this.sortedValues,new SortedByName());
            
        }

        if(sortField.equals("Income")){
            this.sortedValues = this.familyEntryList.toArray();
            Arrays.sort(this.sortedValues,new SortedByIncome());
        }

 throw new IllegalArgumentException("Sorting enties by field '" + sortField + "' is not supported."); 
    }

    
    class SortedByName implements Comparator{
        public int compare(Object entry1,Object entry2) {
            if (entry1 == entry2) {
                return 0;
            }

            FamilyInfoEntry en1 = (FamilyInfoEntry) entry1;
            FamilyInfoEntry en2 = (FamilyInfoEntry) entry2;
            
            return en1.getFamilyName().compareTo(en2.getFamilyName());
        }

        
    }

    
    class SortedByIncome implements Comparator {
        public int compare(Object entry1, Object entry2) {
            if (entry1 == entry2) {
                return 0;
            }

            FamilyInfoEntry en1 = (FamilyInfoEntry) entry1;
            FamilyInfoEntry en2 = (FamilyInfoEntry) entry2;
            return en1.getIncomePerYear() - en2.getIncomePerYear();
        }

    }

}



同样需要注意的是我们把这个实现放到了package com.wukong.test.family.control.impl中
 
下面看看v的bundle实现。

package  com.wukong.test.family.gui;
import  org.osgi.framework. * ;
import  javax.swing. * ;
import  javax.swing.table. * ;
import  java.awt. * ;
import  java.awt.event. * ;
import  com.wukong.test.family.control. * ;
public   class  FamilyInfoGui  implements  BundleActivator, ActionListener,ItemListener  {
    private JFrame mainFrame;
    private JPanel contentPanel;
    private JTable familiesTable;
    private JScrollPane familiesTableScrollPane;
    private JPanel sortedByPanel = new JPanel(new GridLayout(1, 2));
    private JLabel sortedByLabel = new JLabel("Sorted By: ");
    private JComboBox sortedByList = null;
    private JPanel commandPanel = new JPanel(new GridLayout(1, 3));
    private JButton addEntry = new JButton("Add");
    private JButton deleteEntry = new JButton("Delete");
    private JButton updateEntry = new JButton("Update");
    
    FamilyInfoDatabase database = null;
    public void start(BundleContext context) throws Exception {
        Runnable r = new Runnable() {
            public void run() {
                contentPanel = new JPanel();
                familiesTableScrollPane = new JScrollPane();
                database = FamilyInfoDatabase.FamilyFactory
                        .getDatabaseInstance();
                familiesTable = new JTable(new FamilyInfoTableModel(database));
                familiesTableScrollPane.setViewportView(familiesTable);
                
                String[] sortedFields = database.getSortingFields();
                
                sortedByList = new JComboBox(sortedFields);
                
                sortedByList.addItemListener(FamilyInfoGui.this);
                sortedByPanel.add(sortedByLabel);
                sortedByPanel.add(sortedByList);
                commandPanel.add(addEntry);
                commandPanel.add(deleteEntry);
                commandPanel.add(updateEntry);
                contentPanel.add(sortedByPanel, BorderLayout.NORTH);
                contentPanel.add(familiesTableScrollPane, BorderLayout.CENTER);
                contentPanel.add(commandPanel, BorderLayout.SOUTH);
                mainFrame = new JFrame();
                mainFrame.setContentPane(contentPanel);
                mainFrame.setSize(new Dimension(500, 600));
                mainFrame.show();
            }

        }
;
        Thread t = new Thread(r);
        t.start();
    }

    public void stop(BundleContext context) throws Exception {
        this.mainFrame.dispose();
    }

    public void actionPerformed(ActionEvent event) {
    }

    
    
    public void itemStateChanged(ItemEvent event) {
        if(event.getSource() == this.sortedByList){
            String sortingField = (String)event.getItem();
            this.database.sort(sortingField);
            this.familiesTable.repaint();
        }

    }

    class FamilyInfoTableModel extends AbstractTableModel {
        private FamilyInfoDatabase database;
        FamilyInfoTableModel(FamilyInfoDatabase database) {
            this.database = database;
        }

        public String getColumnName(int col) {
            return database.getColumns()[col];
        }

        public boolean isCellEditable(int row, int col) {
            return false;
        }

        public int getColumnCount() {
            return database.getColumns().length;
        }

        public int getRowCount() {
            return database.getRowCount();
        }

        public Object getValueAt(int row, int col) {
            return database.getValueAt(row, col);
        }

    }

}


v的实现基本是界面的构造,而关于数据库,它只能看到interface FamilyInfoDatabase,因为它只import com.wukong.test.family.control.*,然后通过FamilyInfoDatabase内嵌静态类的静态工厂方法获得数据库的实例,这样它完全不用关心数据库如何实现。
 
源码编译后得到class文件后,下一步我们的工作就要来构造这两个bundle。最关键的步骤就是为每个bundle写它的manifest文件
我们先给出mc bundle的manifest文件(familycontrol.mf):
Manifest-Version:  1.0
Bundle-SymbolicName: com.wukong.test.family.control
Bundle-Name: family control
Bundle-Version:  1.0
Bundle-Vendor: LiMing
Export-Package: com.wukong.test.family.control


非常简单,但请大家注意这行
Export-Package: com.wukong.test.family.control
它告诉framework,这个bundle提供com.wukong.test.family.control这个包。
所谓“bundle A提供某个包”意思,通俗简单的理解是如果bundle B在manifest文件中说明要使用这个包(通过Import-Package这个关键字,下面会在v bundle中有说明)那么bundle B运行时,当使用到这个包中的类时,framework将告诉B的class loader这个类的定义是来自bundle A,从而不会发生ClassNotFoundException。另外值得一提的是我们并没有把com.wukong.test.family.control.impl这个包加进来,这样做的目的也是为了隐藏具体实现。将来只要interface不变,我们可以使用不同的实现来替换现有实现,大大提高扩展性。
 
还有一点,细心的话,你会发现这个bundle没有activator。这是允许的,这种bundle就像动态连接库,只提供接口和方法以及实现,等待其他实体的调用,而本身不能运行。
再来看看v bundle的manifest文件(family.mf):

Manifest-Version:  1.0
Bundle-SymbolicName: com.wukong.test.family.gui
Bundle-Name: family gui
Bundle-Version:  1.0
Bundle-Vendor: LiMing
Bundle-Activator: com.wukong.test.family.gui.FamilyInfoGui
Import-Package: org.osgi.framework ; version=1.3,com.wukong.test.family.control


正如上面曾经提到过的一样,我们在Import-Package:关键字中指定该bundle需要使用com.wukong.test.family.control包。在v bundle的源代码中,我们也看到这个bundle的确使用了com.wukong.test.family.control包中的FamilyInfoDatabase。更深入一点,我们可以简单的这样理解,当v bundle运行的时候,framework通过匹配bundle间的Import-Package和Export-Package,
然后告诉v bundle,FamilyInfoDatabase这个类型的定义和装载实际上是由mc bundle完成的。这样,v bundle就会使用mc bundle的class loader来加在这个类型。另外,按照osgi framework的spec规定,javax.swing;javax.swing.table;java.awt;java.awt.event这4个包都都不属于framework的必备包,所以应该在Import-Package中指定。为了不用在Import-Package中指定这4个包,这个例子要求运行在sun的j2se的jvm(比如version 1.4.2_04),这样4个包都作为java api由bootstrap classloader加载,每个bundle都可以直接使用了。
 
有了manifest文件,我们最后就是打jar包了。
比如在windows下,你把两个manifest文件放在包的根目录,然后执行以下命令
jar -cvfm family.jar family.mf com/wukong/test/family/gui/*.class
jar -cvfm familycontrol.jar familycontrol.mf com/wukong/test/family/control
这样,我们就可以认为family.jar是我们的v bundle而familycontrol.jar是我们的mc bundle。
下面,我们就来安装运行这两个bundle吧。
我将首先简单介绍一个我自己编写的osgi framework,然后结合这个demo framework来部署和运行新的“扶贫助手”。
本人编写的osgi framework基本上完成了spec r4的核心规范,但是与安全相关的功能都没有实现。
启动这个framework后,它的shell提供了如下简单的framework管理功能命令:
bl 即bundle list,查看所有已经安装的bundle
dl 即detailed bundle list,用来查看某个bundle的详细信息
sl 即service list,用来查看所有已经注册的service
ls 即list setting,用来查看所有设置的系统属性(System.getProperties)和framework当前的active start level
in 即install bundle,通过指定bundle文件的url来安装该bundle
up 即update bundle,通过指定bundle id来升级指定的bundle
un 即uninstall bundle,通过指定bundle id来卸载指定的bundle
stt 即start bundle,通过指定bundle id来启动指定的bundle
stp 即stop bundle,通过指定bundle id来停止指定bundle的运行
rst 即restart bundle,通过指定bundle id来重新启动指定的bundle
rfr 即refresh package,当某些bundle被更新或卸载后,如果不执行这个命令,那么被更新或卸载的bundle的Export-Package(如果有的话)将继续服役,
也就是说,之前使用这些包的bundle不会因为这个bundle被更新或者卸载而发生变化。而执行这个命令后,受影响的bundle将被重新解析
rest 即restart,重新启动framework,属于“热起”
shut 即shutdown,停止整个framework的运行
set 用来设置framework的active startlevel或者某个bundle的start level
log 用来查看系统的日志信息
现在我们来假设运行环境如下:
OS: window
jvm: j2se 1.4.2_04
family.jar和familycontrol.jar这两个文件放在D:/framework/bundles目录下
第一步:安装bundle
输入以下两条命令:
in file:D:/framework/bundles/familycontrol.jar
in file:D:/framework/bundles/family.jar
然后用bl命令查看结果,其中得到如下显示结果:
Bundle Id Bundle Name Bundle State Start Level Bundle Location     Bundle Symbolic Name
0  OSGiFramework Active  0  System Bundle     system.bundle
.
.(省略部分结果显示)
.
16  family control Installed 1  file:D:/framework/bundles/familycontrol.jar com.wukong.test.family.control
17  family gui Installed 1  file:D:/framework/bundles/family.jar  com.wukong.test.family.gui
说明两个bundle安装成功,其中mc bundle的id是16, v bundle的id是17
第二步:启动bundle
可以输入以下命令
stt 16,17
然后我们就可以看到一个JFrame显示出来,里面显示了3条记录,没有任何顺序(其顺序实际上是在程序中添加到LinkedList的顺序)。我们可以在Sorted By的列表中看到有两个选择“FamilyName”和“Income”,当选择“Income”时,你将发现3条记录按年收入由小到大排列起来。程序的运行完全符合我们的意图。
这时如果我们再用bl命令查看,将得到如下结果:
Bundle Id Bundle Name Bundle State Start Level Bundle Location     Bundle Symbolic Name
0  OSGiFramework Active  0  System Bundle     system.bundle
.
.(省略部分结果显示)
.
16  family control Resolved 1  file:D:/framework/bundles/familycontrol.jar com.wukong.test.family.control
17  family gui Active  1  file:D:/framework/bundles/family.jar  com.wukong.test.family.gui
注意:由于mc bundle没有Activator,所以启动这个bundle只会使其进入Resolved状态。

有了这样的结构,程序变得灵活些了。现在假设客户提出需要增加一个字段,即人均年收入,并且提供按人均年收入排列纪录。看看framework框架下,这样的变动是如何的简单!
首先,我们通过分析,发现只要更改mc bundle的代码,使得数据库的实现中增加这个字段以及相应的排序方法即可。更新后的代码如下:

package  com.wukong.test.family.control.impl;
import  com.wukong.test.family.control.FamilyInfoDatabase;
import  java.util. * ;
public   class  FamilyDatabase  implements  FamilyInfoDatabase  {
    private LinkedList familyEntryList = new LinkedList();
    private Object[] sortedValues = null;
    public FamilyDatabase() {
        this.familyEntryList.add(new FamilyInfoEntry("Zhang",3,1260));
        this.familyEntryList.add(new FamilyInfoEntry("Li",6,1800));
        this.familyEntryList.add(new FamilyInfoEntry("Liu",4,1500));
        this.sortedValues = this.familyEntryList.toArray();
    }

    public String[] getColumns() {
        return new String[] { "Family Name", "Family Population", "Income" ,"IncomePerPerson"};//添加了“IncomePerPerson”字段
    }

    public Object getValueAt(int row, int column) {
        FamilyInfoEntry entry = (FamilyInfoEntry)this.sortedValues[row];
        switch (column) {
        case 0:
            return entry.getFamilyName();
        case 1:
            return new Integer(entry.getPopulation());
        case 2:
            return new Integer(entry.getIncomePerYear());
        case 3:
            return new Integer(entry.getIncomePerYear()/entry.getPopulation());//计算人均年收入
        default:
            throw new IllegalArgumentException("Invalid column index.");
        }

    }

    public String[] getSortingFields() {
    }

    public int getRowCount() {
        return this.familyEntryList.size();
    }

    public void addEntry(List columns, List values)
            throws IllegalArgumentException {
        // TODO Auto-generated method stub
    }

    public void deleteEntry(String familyName) {
        // TODO Auto-generated method stub
    }

    public void update(String familyName, List columns, List values)
            throws IllegalArgumentException {
        // TODO Auto-generated method stub
    }

    public void sort(String sortField) throws IllegalArgumentException{
        if(sortField.equals("FamilyName")){
            this.sortedValues = this.familyEntryList.toArray();
            Arrays.sort(this.sortedValues,new SortedByName());
            
        }

        if(sortField.equals("Income")){
            this.sortedValues = this.familyEntryList.toArray();
            Arrays.sort(this.sortedValues,new SortedByIncome());
        }

        if(sortField.equals("IncomePerPerson")){//对纪录按人均年收入进行排序
            this.sortedValues = this.familyEntryList.toArray();
            Arrays.sort(this.sortedValues,new SortedByIPP());
            
        }

    }

    
    class SortedByName implements Comparator{
        public int compare(Object entry1,Object entry2) {
            if (entry1 == entry2) {
                return 0;
            }

            FamilyInfoEntry en1 = (FamilyInfoEntry) entry1;
            FamilyInfoEntry en2 = (FamilyInfoEntry) entry2;
            
            return en1.getFamilyName().compareTo(en2.getFamilyName());
        }

        
    }

    
    class SortedByIncome implements Comparator {
        public int compare(Object entry1, Object entry2) {
            if (entry1 == entry2) {
                return 0;
            }

            FamilyInfoEntry en1 = (FamilyInfoEntry) entry1;
            FamilyInfoEntry en2 = (FamilyInfoEntry) entry2;
            return en1.getIncomePerYear() - en2.getIncomePerYear();
        }

    }

    
    class SortedByIPP implements Comparator {//人均年收入的排序标准。
        public int compare(Object entry1, Object entry2) {
            if (entry1 == entry2) {
                return 0;
            }

            FamilyInfoEntry en1 = (FamilyInfoEntry) entry1;
            FamilyInfoEntry en2 = (FamilyInfoEntry) entry2;
            return (en1.getIncomePerYear()/en1.getPopulation()) - (en2.getIncomePerYear()/en2.getPopulation());
        }

        
    }

}




编译完毕后,我们把mc bundle的manifest文件改为如下:

Manifest-Version:  1.0
Bundle-SymbolicName: com.wukong.test.family.control
Bundle-Name: family control
Bundle-Version:  2.0  //由1.0改为2 .0
Bundle-Vendor: LiMing
Export-Package: com.wukong.test.family.control


然后使用jar工具打包,并把产生的新的familycontrol.jar依旧放在D:/framework/bundles目录下。
这时,我们只要执行下面的命令,framework就完成对mc bundle的升级工作:
up 16
升级完毕后,你会发现v bundle的显示依旧没有任何变化。这时我们需要执行一个refresh package命令,来更新bundle的解析:
rfr
这时,你会发现原来的JFrame被关闭了,然后又一个JFrame显示出来,里面的纪录多了一列“IncomePerPerson”,而且在“Sorted By”里面也
多了“IncomePerPerson”,而且,排序的结果也很正确。
瞧,framework为应用程序提供了强大的动态更新功能,非常方便。甚至都不用重新启动framework,更不用说JVM了。您也许会说,最终用户根本不可能帮你输入这些什么in,up晦涩的命令。还有,让用户拷贝新版本到本地似乎也不是什么好主意。嗯,这个问题说得很对。其实我是偷懒了,这些操作framework都留有接口,我们只要再编写一个专门管理这两个bundle升级的第三个bundle就可以了,这个bundle将提供友好的界面来告诉最终用户如何升级。这样就能够提供比较好的解决方案了。至于第二个问题,别忘了bundle的location是一个url,只要jvm注册了相应的url handler完全可以支持http,ftp等丰富的url,例如,升级的时候,framework自动连接到供应商的http下载服务器获取最新版本进行更新,当然,我们也可以把更强大更灵活的升级功能及选项加入到上面提到的第三个bundle中,从而极大提高了程序的易用性,而且极大降低了软件提供商的维护成本。
 
到此为止,我已经想不出再多好话了,但是,还可以更好!下一节,将采用service的方式来实现,嘿嘿,情况又会不一样了,到时候我会对比一下这两种实现方式的优劣。
 
题外话:抱歉没有拿某个著名的产品或者open source的产品来举例,我打算把自己的实现也opensource,有兴趣参与吗?不管怎样,过两天就把实现上传上来,欢迎拍砖。

整理并记录几种运算放大器 运算放大器是一种十分常见的电子元器件,最近我在学习运放,以前在学校没有好好的学习,今天在B站看了唐老师讲运算放大器-唐老师讲电赛系列视频教程,记录下所学的,纯当是自己的笔记 学习运放,有两个重要的概念及重要的计算法宝,虚短vp=vn;和虚断ip=in 1反向比例运算电路 Rf可以大于、小于或等于R,起到放大、跟随、衰减输入的作用; 平衡电阻没有太高的精度要求,可加可不加; 有些运放内部集成了补偿电路,就不需要使用平衡电阻,加了反而增大误差,如OPA227 2.同向比例运放电路 . 阅读详情

相关推荐

Qt5.12.12安卓开发环境搭建:Windows下避开SDK版本坑的保姆级教程

本文提供Qt5.12.12在Windows下搭建Android开发环境的详细教程,重点解决SDK版本兼容性问题,特别是cmdline-tools与JDK8的匹配陷阱。通过精准选择组件版本、手动配置路径和修复常见错误,帮助开发者高效完成环境配置,适用于Qt跨平台移动开发。

weixin_33737774的博客 542

OSGi 框架加载Bundle方法及OSGi常用命令

1.将插件模块导出。 2.启动OSGi框架 第一种方式导入Bundle  在osgi>中输入 install reference:file:D:\work_soft\OSGI\plugins\OSGI_HelloWord_1.0.0.jar 回车 第二种方式导入Bundle  在OSGi框架目录下(即与org.eclipse.osgi_3.3.0.200704022148.jar文件并...

iteye_20293的博客 1475

二阶高通滤波器硬件设计:5种RC到有源方案对比与选型

在传感器前端和音频信号调理中,二阶高通滤波器是抑制直流偏移与低频干扰的关键模块。其设计核心围绕截止频率、品质因数Q、增益与噪声四个指标展开,其中Q值决定滤波器在转折频率附近的响应形状,如Butterworth最大平坦响应需Q=0.707。从纯无源RC电路到引入运放的有源拓扑,演变逻辑在于解决负载效应、提供增益并借助反馈提升Q值。实际工程中,RC级联、VCVS(Sallen-Key)、状态变量及回转器模拟电感等方案各有适用场景:RC电路简单但Q值受限,Sallen-Key单运放即可实现高Q,状态变量适合Q值独

weixin_32770423的博客 97

你好,OSGi (第一部分): Bundles入门

Normal 0 false false false EN-US X-NONE X-NONE

carlwu的专栏 1978

快速傅里叶变换(FFT)的汇编实现在DSP开发中

在数字信号处理(Digital Signal Processing,DSP)开发中,使用汇编语言实现FFT可以进一步提高计算性能和优化系统资源的使用。FFT是一种分治算法,它通过将一个长度为N的离散时间域序列分解为多个长度为N/2的子序列,然后递归地进行计算。开发者可以根据实际需求,结合具体的硬件平台和编译器工具链,对FFT的汇编实现进行优化和定制化。需要注意的是,上述示例代码中只给出了FFT的基本框架,具体的合并操作及其他细节需要根据实际需求进行实现。上述示例代码演示了一个简单的FFT汇编实现。

QoTypescript的博客 683

YOLO26改进目录一览 | 涉及卷积层、轻量化、注意力、损失函数、Backbone、SPPF、Neck、检测头等全方位改进

1️⃣ 什么!不知道如何改进模型⁉️ 本专栏已更新260多种不同的改进方法,所使用并改进的每一个模块均包含详细的模块分析、原理讲解、个人总结、多种改进方式以及完整的修改流程,所有改进100%可直接运行,性价比极高。2️⃣ 找不到合适的模块⁉️ 所有改进点均为近三年顶会,顶刊提出的先进算法,将其融入到中,并进行二次创新,新颖度高,创新度高,能够适应不同的任务场景。3️⃣ 不确定自己改进的步骤、结果是否正确⁉️ 订阅专栏即可进群享受模型训练、模型改进、论文写作、投稿选刊,从入门到论文的各种答疑内容,非常适合新手

Limiiiing的博客 6317

OSGI-Bundle:概念和入门

简单的来说就是平台应用和bundle应用,如何将平台应用和bundle应用整个的运行起来,其中最关键的就是对bundles的控制,包括bundle安装、开启、关闭、更新和卸载。: bundle 是以 jar 包形式存在的一个模块化物理单元,里面包含了代码,资源文件和元数据(metadata),并且jar包的物理边界也同时是运行时逻辑模块的封装边界。实际工作中可以理解为bundle是一个小应用,一般是业务扩展方维护这个应用,里面有各种自身的业务逻辑和对平台应用的扩展。

master-dragon的专栏 821

3 ATK2(AUTOSAR OS)代码移植-目标硬件及编译环境简介

该部分介绍ATK2代码移植的目标硬件以及编译环境

xiaoduanduansad的博客 717

OSGi (第一部分): Bundles入门(翻译)(转)

新建、执行和管理OSGi容器中的Bundles 摘要: OSGi(Open Service Gateway Initiative,开放式服务通路倡议)为开发和部署模块化应用和库定义了基础架构。在本文中,Sunil Patil为我们介绍了OSGi开发的概念,并使用Eclipse自带的OSGi容器Equinox创建了一个简单的Hello World应用;同时...

CCbleach的专栏 1859

MIKE水动力笔记8_冷启动与热启动

在【MIKE水动力笔记5_建立水动力模型】中,讲到【Step 2 设置模型参数】中的【Initial Conditions】时,提到了冷启动与热启动。本博文就详细讲解何为冷启动、热启动,并通过一个案例具体分析两者不同。...

晏长街的博客 6568

在 SAP BAS 中扩展标准 SAP Fiori 应用并部署到 ABAP 环境的完整实践指南

SAPUI5 Adaptation Project 摘要(148字) SAPUI5 Adaptation Project 提供了一种高效扩展标准Fiori应用的方式,通过创建应用变体(Application Variant)实现差异化定制。开发者可在SAP BAS中使用可视化编辑器修改UI元素(如隐藏字段、调整表格布局、添加按钮等),而无需重写业务逻辑。变体部署到ABAP环境后,可与标准应用并行使用,且能随原应用升级保持同步。典型应用场景包括为不同用户角色定制简化界面或增强特定功能,既满足个性化需求,又保留

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 183

java bundle id_OSGi介绍(五)两个bundle

(四)中提到的直接型改造法实际上和一个传统的java应用程序没有区别。因此客户的需求发生变化,通常是牵一发而动全身。那么我们现在就看看如果在osgi framework中,用多个bundle来实现的效果吧。我的想法是用两个bundle来配合实现“扶贫助手”的功能。一个bundle专门负责录入和显示纪录,一个bundle专门负责纪录的数据结构和对数据的处理,用时下时髦的说法就是使用了mvc,只是我的...

weixin_39604280的博客 317

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

OSGI BUNDLE

<br />开发一个简单的Hello World的OSGi Bundle(OSGi绑定包)<br />在OSGi中,软件是以Bundle的形式发布的。一个Bundle由Java类和其它资源构成,它可为其它的Bundle提供服务,也可以导入其 它Bundle中的Java包;同时,OSGi的Bundle也可以为其所在的设备提供一些功能。Eclipse为开发OSGiBundle提供了优秀的 支持,它不仅提供了向导来创建OSGi Bundle,而且还提供了内嵌的Equinox容器,您可以使用该容器执行和调试

码龙008 1113

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

OSGi Bundle Convert插件原理

本文首发于Infoq中文站(4.2):http://www.infoq.com/cn/articles/osgi-bundle-convert-plugin-principle   1.引言 普通的web应用要转换为OSGi应用,经常会遇到应用中依赖的Jar是非标准的情况,这些Jar可能只遵守了部分OSGi规范,甚至Manifest信息是空的。这种情况在OSGi 应用中根本无法使

不才的专栏 5512

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

【OSGi】2. bundle与模块化

模块层是OSGi框架的最基础层次,是OSGi其他部分的基础。 1、模块 定义: 一个从逻辑上封装实现类的集合,一个基于实现类子集的可选公共API,一个对外部代码依赖关系的集合。 package是Java提供的一种内建的模块化方式,但它有一些限制:http://blog.youkuaiyun.com/vking_wang/article/details/9735395 以上讨论的都是“

Alpha's 学习笔记 9005

浅析OSGI的bundle依赖

From: http://www.xeclipse.com/?p=1165 Bundle是OSGI中的基础元件,不同的bundle之间可以相互依赖、引用,这样许多bundle才会共同协作,实现一些比较复杂的功能。Bundle的依赖一直是一个比较棘手的问题,包括Lazy start等,下面我们具体Bundle依赖到底是怎么一回事。 测试场景:Eclipse 3.6, Equinox

Seven's Rainbow Paradise 3268

在Eclipse中开发OSGi Bundle

Eclipse为开发OSGI Bundle提供了良好的支持,它不仅提供向导来创建OSGi Bundle,而且还提供了内嵌的OSGi框架实现(即Equinox容器),可以使用该容器执行和调试Bundle。从本质上说,每一个Eclipse插件都是一个OSGi Bundle,只不过这个OSGi Bundle增加了一些Eclipse专用的代码而已。下面通过具体的例子来介绍如何用Eclipse来开发OSGi...

程序员的天堂 742

OSGI框架下,bundle的两种启动方式

什么是Bundle? 如果有人问你,什么是osgi?其最大特点是什么?你只要回到"模块化开发体系",足矣。要是你能说出来java9的模块化开发体系并与之对比,那就说明你是专业的。 既然是模块化开发体系。那么osgi中的模块就是bundle,bundle是osgi中的最基本单位。 osgi中的bundle是jar文件格式规范基础上扩展出来的,一个符合osgi规范的bundle首先必须是一个符合

huakai_sun的博客 8214

OSGi起步(3):bundle之间的依赖

-----------------------原文出处:http://www.eclipsezone.com/eclipse/forums/t90544.html原作者:Neil Bartlett  ----------------------OSGi起步(3):bundle之间的依赖 在之前的教程中,我们知道bundle怎么启动和停止,以及它们如何与框架、以及相互间的生命

瓶子的窝 4184

osgi中manifest中属性介绍

1) 描述性的属性Bundle-Name: Simple Paint API                                                      #1Bundle-Description: Public API for a simple paint program.            #2Bundle-DocURL: http:

flyingamy的专栏 2677

java里Bundle是什么_OSGi 体系结构及Bundle简介

1、OSGi 的体系架构是基于插件式的软件结构,包括一个 OSGi 框架和一系列插件,在 OSGi中,插件称为 Bundle,其中,OSGi 框架规范是 OSGi 规范的核心部分,它提供了一个通用的、安全可管理的 Java 框架,通过这个框架,可以支持 Bundle 服务应用的部署和扩展。Bundle 之间可以通过 Import Package 和 Require-Bundle 来共享 Java ...

weixin_34409887的博客 1887

利用 Eclipse 开发基于 OSGi 的 Bundle 应用[摘]

开放服务网关协议 (Open Services Gateway Initiative),简称 OSGi,为网络服务定义了一个标准的、面向服务的计算环境,为用户提供了开放的、面向服务组件的、易于部署的编程模型,这个编程模型允许用户将定义好的接口规范绑定到 OSGi 运行环境中的特定Service,在构件 SOA 面向服务为中心的企业应用的过程中,OSGi 技术正发挥越来越重要的作用。在本文中,将介绍

SQ 1033

将普通jar文件打包成osgi bundle的方法

  最近更新列表 1.IBM的aix中安装jdk(7月21更新)2.Linux(CentOS)中安装jdk (7月21更新)3.Linux(CentOS)安装weblogic (7月22更新)4.Aix系统中安装webLogic (7月22更新)5.IBM实体机aix中创建weblogic域 (7月23更新)6.linux中通过VNC创建weblogic域 (7月23更新)7.在RedHa...

zl19861225的专栏 1147

OSGi介绍(四)第一个bundle

<br />先给出“扶贫助手”的第一种改造,我称之为“直接型”,请看:<br /><br />package aa.bb.cc;<br />//需要import osgi的核心package<br />import org.osgi.framework.BundleActivator;<br />import org.osgi.framework.BundleContext;<br />//实现了BundleActivator<br />public class FamilyInfo implements 

immcss的专栏 1289

ODL开发背景知识简介-------OSGi、Bundle、karaf、Feature

ODL开发背景知识简介OSGi(Open Service Gateway Initiative)OSGI框架BundleBundle生命周期Bundle间的依赖karafFeature OSGi(Open Service Gateway Initiative) OSGi(Open Service Gateway Initiative,直译为“开放服务网关”)实际上是一个由OSGi联盟发起的Java为技术平台的动态模块化规范,OSGi不是一个应用层面的框架,而是设计层面的规范。软件设计就不外乎复用、内聚、耦合

落了一地秋的博客 1184

OSGi介绍及OSGi的Bundle应用

http://blog.sina.com.cn/s/blog_50356fbb0100dytp.html 关键字: OSGi Bundle Plugin Eclipse     开放服务网关协议 (Open Services Gateway Initiative),简称 OSGi,为网络服务定义了一个标准的、面向服务的计算环境,为用户提供了开放的、面向服务组件的、易于部署的编程模型,这个编

走马观花 1762
上一篇: OSGi介绍(四)第一个bundle
下一篇: OSGi介绍(六)OSGi的service
ShenRui
博客等级 码龄20年 63粉丝 36原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值