Original URL: http://sangmin214.iteye.com/blog/784131
Chapter 2 proficiency
This is mainly about osgi's modularity. What is atomicity? Generally, why is regionalization so important, and how it will benefit you from future Java development, construction, and maintenance.
Specifically, this chapter describes the metadata of osgi bundle and how to use the metadata to describe the adequacy of your application. Of course, there is another example.
2.1 What is adequacy
What is a module? Generally, a complete system consists of several relatively independent blocks, which are called modules. The module defines the logical boundaries that can be implemented. The internal details can only be visible within the module, and the outside can only see the explicit public part of the module.
2.1.1 adequacy vs. Object-oriented
The difference between attention and object orientation is that they all isolate attention, that is, to separate a system into a unit with a small overlap, and then you can break through each other. When your system requires some functions, you sit down and write some classes to implement the required functions. In most cases, you can write many classes or use third-party class libraries. After your application is completed, the logical relationships between classes are all reflected in the lower-Layer Code level. From the class name, it is difficult for you to determine the dependency between classes unless you read the code yourself. Therefore, classes encapsulate data rather than code. The module encapsulates the code. In fact, the package in Java is also a form of code encapsulation, but its function is relatively weak. Therefore, in Java Development, object-oriented programming can be seen as a module implementation method. You use objects to build modules. Therefore, the development of separate classes focuses on the implementation of specific functions from the beginning, while the module focuses on the overall structure of the application from the beginning.
Module Definition: Some implementation classes that are logically encapsulated + optional public APIs Based on implementation classes + dependency on external code
Tip: Logical atomicity vs physical atomicity
The module defines the logical boundaries of your application and affects code visibility. The adequacy of logic refers to code visibility. Physical controllability refers to the packaging and deployment methods of your code. In osgi, these two concepts are basically merged. But they are different concepts in terms of atomicity.
2.1.2 Vehicle License
I explained the example of a car to explain that different modules may need the same classes. However, if different classes are used, Java cannot implement them, because Java always uses the class first found in the class path. I don't fully understand this example and what the author wants to express.
2.2 why Modularization
Modularization is designed to ensure high cohesion and low coupling of your applications. High Cohesion means that each module of your application only provides independent functions. Low coupling means that the dependencies between modules should be minimized.
More specifically, once you use osgi to modularize your application, all dependencies on external code will be declared, making reuse easier, because you no longer need to go through the document to check which other class libraries you need. In addition, because of the adequacy of your applications, each application group can develop its own modules, which is especially suitable for multiple groups of multi-site development projects or large open-source projects.
2.3 modular a simple painting Program
I will not go into details here.
2.4 bundle Introduction
Bundle definition: a modular physical unit, generally in the form of jar packaging, including code, resource files and metadata. The boundary of the JAR file is also the encapsulation boundary of the runtime logical unit.
The main difference between a bundle and a common jar package is that the bundle contains module metadata. Although all jar files have manifest. MF files.
2.4.1 bundle's role in physical adequacy
You don't need any additional data to determine whether a class belongs to a module. If you put your class in the jar package, it indicates that your class belongs to this module. Therefore, bundle is also the deployment unit of your module. The metadata of bundle is stored in the manifest file. This metadata should be stored in the manifest file or directly in the source file (in the form of annotation), which has been controversial in the industry. The book provides a tip to describe in detail their respective advantages and disadvantages. The benefits of storing metadata in a manifest file are as follows:
· When you make changes to the metadata, you do not need to re-compile the bundle.
· You do not need to access the code area to add or modify metadata
· You do not need to load classes to virtual machines to access related metadata.
· Your code does not need to rely on osgi APIs, so that you can use your code in other frameworks
· You can use your code in multiple modules
· You can run your code on an older or non-annotation-supported virtual machine
2.4.2 role of bundle in logic adequacy
Bundle's role in logic adequacy mainly controls code visibility. You must specify in the metadata which packages of your bundle can be accessed externally. Otherwise, the class in your package is public and cannot be accessed externally.
2.5 use metadata to define bundle
Metadata related to modules mainly includes the following three types:
· Human-readable information-this information is optional and is intended only for bundle users.
· Bundle identification-this information is used to uniquely identify a bundle.
· Code visibility-this information is used to define which codes are internally visible and which internal codes are externally visible.
The book provides a tip to explain in detail the syntax of the JAR File Manifest file.
2.5.1 manual-readable information
The manual-readable information mainly provides some information, such as what the bundle is, where it comes from, and so on. It mainly helps the bundle users understand it. The following is an example:
Bundle-Name: simple paint API
Bundle-Description: public API for a simple paint program.
Bundle-docurl: http://www.manning.com/osgi-in-action/
Bundle-category: example, library
Bundle-vendor: osgi in action
Bundle-contactaddress: 1234 Main Street, USA
Bundle-copyright: osgi in action
These attributes are intuitive, and the information is directly ignored by the osgi framework. Therefore, you have a great degree of freedom to define these attributes.
2.5.2 bundle Recognition
Bundle-symbolicname is used by the osgi framework to uniquely identify a bundle. Its value is similar to the Java package and is separated by vertices, we recommend that you use the inverted write of your domain name to prevent name conflicts. With bundle-symbolicname, it is not enough because once you modify your code, you need an attribute to indicate the version of your code, and this version information can be recognized by the osgi framework. In general, bundle-symbolicname + bundle-version can uniquely determine a bundle. However, in the osgi 4 specification, bundle-symbolicname is determined as a required attribute. Therefore, to be compatible with the previous bundle, osgi adds an attribute bundle-manifestversion, this attribute currently has only one value of 2. All bundle with this bundle-manifestversion attribute must have the attribute that uniquely identifies this bundle (bundle-symbolicname + bundle-version ).
There is a tip in the book that describes in detail how to write a version.
2.5.3 code visibility
Metadata describing code availability mainly includes the following information:
1. Class path of the internal bundle-this is the code that makes up this bundle
2. Code exposed to the public-the Code exposed to the public
3. Introduced external code-these are external code on which internal code depends
Code visibility and class path of standard jar files
In general, we compile the class and package it into a jar package. If the manifest file in the jar package has the specified main-class attribute, we can run your jar package as follows:
Java-jar app. Jar
If this parameter is not specified, we can add it to the class path and run it like this:
Java-CP app. Jar org. Foo. Main
Java will find and run the main function. When your program runs, all required classes will be searched through the class path. The class path includes those jar packages and standard JRE classes. There are two problems:
1. In the jar package, how do I find the classes you need?
2. How to expose internal classes to external access?
For the first problem, Java searches the root directory of the jar package and uses the package field separated by vertices as the file directory. For the second problem, by default, all classes starting from the root directory of all jar packages are made public. The class path defines which external classes are accessible to the internal classes in our jar package, and all the classes in the class path are visible to our application classes, even if they are not necessary.
Class path of the internal bundle
Unlike Common jar packages, all classes are visible by default. In bundle, you must specify in the bundle class path which classes are visible to other classes in the jar package.
Bundle-classpath: an ordered list separated by commas (,). It is used to find the list of relative paths in jar packages of classes and resources.
For example:
Bundle-classpath:., other-classes/, embedded. Jar
In this case, the osgi framework will look for a class within the bundle as follows: first, it will look for this class in the bundle root directory. If there is no, it will be searched in the folder named other-classes, and then in embedded. jar. If you do not define it, the default value of bundle's class path is., that is, the root directory. Note that when you do not assign any value to bundle-classpath, it has a default value .. Once you assign a value, if you want to add. To the class path, you must add it as shown in .. This value is not the default class path added to the bundle.
Export internal code
The standard jar package exposes all classes for external use, and bundle must indicate which classes are accessed by external users.
Output package definition: A group of internal packages for external access separated by commas
In osgi, classes between modules are shared at the package level. This is an example:
Export-package: org. Foo. Shape, org. Foo. Other
Because different bundle may output the same package, we can add some attributes to the bundle, such:
Export-package: org. Foo. shape; vendor = "Manning", org. Foo. Other; vendor = "Manning"
In addition to the bundle version, osgi also supports the package version. For example:
Export-package: org. Foo. shape; org. Foo. Other; version = "2.0.0"
The default package version is 0.0.0.
Import external code
You must use import-package to display the external code you need to import. However, all classes in the Java. * package are exceptions, and the osgi framework automatically sets them to visible.
Import-package vs. Import keyword
The import keyword is only used for namespace management, so that you do not need to output the full package name of a class. Therefore, you do not need to use the import keyword. The import-package is important to the osgi framework because it allows the osgi framework to know the classes required by your bundle.
Import-package definition: A list of packages from external bundle required by a set of comma-separated internal bundle code. For example:
Import-package: org. Foo. Shape, org. Foo. Shape. Other
You can specify some attributes for your import package. For example:
Import-package: org. Foo. shape; vendor = "Manning"
This extra property is like a filter.
When the osgi framework is parsing dependencies, It will compare whether the vendor attribute of the packages imported from the external is the same as this. However, by default, it is acceptable that the provided version is newer or the same as the required version. Of course, you can also specify the range of acceptable versions more accurately.
However, the use of package instead of directly using bundle for class sharing among bundle has been controversial in the industry. The book provides a tip to discuss this issue. I was deeply impressed by its explanation: bundle-level dependencies depend on someone, while package-level dependencies depend on something. If the other person provides the same thing, you have no reason to stick to that person. And when your bundle grows sufficiently large, you may want to refactor your bundle. In this case, all bundles dependent on this bundle must be changed. In addition, a bundle may depend on only a few packages in the other bundle, rather than all packages.
2.5.4 search sequence
When a bundle is running, a class is required. The framework search sequence is as follows:
1. If the class comes from a package whose name starts with Java., the parent class loader will load the class. If this class is found, this class is used. If this class is not found, the query ends and an exception is thrown.
2. If this class comes from an imported package, the framework will export the package to find this class. If yes, use this class. If no, the query ends and an exception is thrown.
3. Find the bundle class path. If yes, use this class. If no, the query ends and an exception is thrown.
Note: Is a bundle a jar package or a jar package a bundle?
Is the jar package a bundle? Indeed, the jar package is a bundle, but it does not provide any module metadata and it does not provide any available classes to the outside world, so it is useless at all.
Only bundle's class path contains. Bundle and can be used as a common jar package.
2.6 end our drawing program design
This drawing program has designed three bundle, one is the shape API, the other is the shape impl, the other is the interface implementation, and the other is the window program using graphics.
2.6.1 improve the modularization of our Plotting Program
The implementation of each graph is divided into independent bundle.
2.6.2 start a new drawing program
Here we use a general osgi bundle starter to start our plotting program:
Java-jar launcher. Jar bundles/
This initiator will create an osgi framework instance and deploy all the bundle in the bundles folder. The specific implementation of the relevant starters will be discussed in the subsequent sections.
2.7 osgi dependency parsing
This section describes how osgi resolves the package dependency of bundle and how to ensure package consistency between bundles.
2.7.1 automatic dependency parsing
An important task completed by the osgi framework is automated dependency management, also called bundle dependency parsing. The dependency of a bundle must be parsed by the Framework before it can be used.
Definition of resolution: a bundle import package is matched to the export package in a unified manner, so that each bundle dependency package has only a version.
Parsing a package will cause parsing of other packages, if the export package you depend on is not parsed. All packages that pass dependencies are parsed once until all packages are parsed. If one of the dependencies cannot be met, the parsing will fail. The package you first parsed cannot be used until all its dependencies are satisfied.
There are three problems:
1. When will the framework parse the dependencies of a bundle?
2. At the beginning, how did the framework access the bundle and start parsing?
3. What does it mean to connect the import bundle to the export bundle?
First, when other bundle attempts to access a bundle, the framework will automatically parse the bundle.
The second problem is that the framework is parsed only when a bundle is installed in the framework.
The third problem is that each osgi bundle is connected with a Class Loader during execution, which is also how each bundle can access the classes it needs to access. When an import bundle is connected to an export bundle, the class loader of the import bundle gets a reference pointing to the class loader of the export bundle, then, if you need to access the classes of the exported bundle to import the bundle, the class loader of the imported bundle can delegate this request to the class loader of the exported bundle.
Simple Example
Dependency parsing is actually quite intuitive. The framework only needs to match the export to the import.
TIPS: system class path proxy
The classes provided in JRE are generally accessible by default.
If attributes are specified in the import, dependency parsing also matches the attributes. You can also add version information to the import as a restriction.
Multi-vendor situation
The previous example is relatively simple, because only one bundle is provided in the package required for importing bundle. How will the framework Parse Multiple matched export bundle? If multiple versions of package are available for connection, the Framework selects the highest version. What if the version is the same? The framework is first installed. In another case, the Framework selects the parsed packages first. Therefore, the priority of dependency resolution is summarized below:
1. The resolved packages have the highest priority. If all the parsed packages have been resolved, the packages will follow the version and installation sequence.
2. The installed versions and installation sequence of packages not parsed
2.7.2 ensure consistency of use restrictions
For a bundle, all packages visible to it are called its class space. Therefore, the class space of a bundle is the class path of the package it imports and Its bundle. The class space of all bundle must be consistent. If I use a certain version of Class A, other bundle installed in this framework must be of the same version if I want to use Class. This document provides an example. An HTTP service requires a servlet of Version 2.3, and the framework also has a servlet of Version 2.3. The HTTP client requires a servlet of version 2.4, and the httpclient calls the HTTP service method. Which version of the servlet in this method should be used? If the two bundle are installed at the same time, it is relatively simple and the framework will select a newer version 2.4. If HTTP
Service indicates that only 2.3 is allowed, while HTTP client indicates that only 2.4 is allowed.
Instructions: List of comma-separated packages attached to the exported package
Example:
Export-package: org. osgi. Service. HTTP;
Uses: = "javax. servlet"; version = "2.3.0"
Import-package: javax. servlet; version = "2.3.0"
In this case, all bundle that uses this bundle must use servlet 2.3.
Use uses
2.8 Review advantages of modular plotting programs
Logic boundary Enhancement
Improved reusability
Configuration Verification
Version Verification
Configuration flexibility
2.9 conclusion
Attention provides a form of separation of attention, which provides logical and physical class encapsulation.
Modularity is required because it allows us to split our applications into logically independent blocks that can be modified separately.
Bundle is the name of a module in osgi. It is actually a jar package containing code, resource files, and module metadata.
Module metadata contains human-readable information, bundle identification information, and code visibility information
Bundle code visibility includes internal class paths, export packages, and import packages
Before bundle is available, the osgi framework uses the metadata of the import package and the export package to automatically parse bundle dependencies and ensure type consistency.
The imported package and the everywhere package contain the package dependency between packages, and the "uses" constraint contains the dependency of the package within the bundle to ensure the complete type is consistent.