The significance and purpose of Java Dynamic Loading class:
Java Dynamic Loading class is mainly used to operate different objects to execute different functions without changing the main program code. It is mainly conducive to system expansion. For example, when I want to change a function, I only need to create a class, then write the corresponding functions, and the new functions can be used through the configuration file, you do not need to modify any part of the system. You only need to add a class, which fully achieves loose coupling. The principle of opening/closing is met (modification is disabled, and addition or deletion is enabled );
Dynamic Loading Design Mode
Several important concepts
Interface: defines a bunch of unimplemented methods (namely Abstract METHODS). The specific implementation of these methods is implemented by the class to implement this interface.
Class. forname (string classname): converts a given string to a class type using the forname method, for example, class. forname ("integer") can generate an integer type. The newinstance () method can be used to generate objects of this class. For example, arraylist
Arr = (arraylist) class. forname ("arraylist"). newinstance ()
This generates an arraylist object arr, through which you can call the method of the arraylist class. Note: The class of the string corresponding to classname must have a construction method without any parameters.
Implementation Process of Java Dynamic Loading class (for example, car creation)
1. Create an interface (icarfactory) that has an unimplemented method makecar () used to make a car.
2. There are two classes that implement the icarfactory interface, so they also implement the makecar () method.
Bydfactroy class ---------------- makecar () is used to manufacture BYD, which implements the specific method of manufacturing BYD.
Bmwfactroy class -------------- makecar () is used to manufacture BMW. He has implemented the specific method for manufacturing BMW.
3. Create the configuration file XML to write the corresponding class name (class full name = package name + class name) to the corresponding location;
4. create a main program class. Declare An icarfactory type variable ICF, read the corresponding class name from XML, and call class. forname (classname ). instance () gets an instance of a specific class and assigns it to ICF. Finally, a car can be built by calling makecar () through ICF.
Note: The jar package used in this experiment is a dom4j-1.6.1.jar, of course you can also read from the property or directly use Java to parse the XML class so that you do not need this external jar package.
Create Interface
|
Package dynamic. test;
// The interface is used to know that a car has an abstract method makecar (). To implement its class, you must implement this method.
Public interface icarfactory {
Public void makecar (); // car creation method waiting for implementation
} |
Create two classes that implement the interface
|
// Create a bydfactory class to implement icarfactory
Package dynamic. test;
Public class bydfactory implements icarfactory {
// Implements the makecar () method of icarfactory
Public void makecar (){
System. Out. println ("bydfactroy made a BYD for you ");
}
}
// Create a bmwfactory class to implement icarfactory
Package dynamic. test;
Public class bmwfactory implements icarfactory {
// Implements the makecar () method of icarfactory
Public void makecar (){
System. Out. println ("bmwfactroy made a BMW for you ");
}
} |
Create the configuration file factory. xml
|
<Factory>
<! -- The full name of the corresponding car building factory class. Currently, the program can select Dynamic. Test. bmwfactory or dynamic. Test. bydfactory -->
<Factroy-Name> dynamic. Test. bydfactory </factroy-Name>
</Factory> |
Create the main class of the Test Program
|
Package dynamic. test;
Import java. Io. file;
Import org. dom4j. Document;
Import org. dom4j. extends entexception;
Import org. dom4j. element;
Import org. dom4j. Io. saxreader;
Public class testmain {
// Main class of the test program;
Public static void main (string [] ARGs ){
// Declare the variable icf of the icarfactory type.
Icarfactory ICF = NULL;
Try {
// Refer to the small experiment for reading and writing XML.
File file = new file ("lib/factory. xml ");
Saxreader reader = new saxreader ();
Document Doc = reader. Read (File );
Element root = Doc. getrootelement ();
String classname = root. elementtext ("factroy-name ");
// Obtain the corresponding Class and Class instance through classname and assign it to ICF; ensure that the classname
// The corresponding class has a construction method without Parameters
ICF = (icarfactory) class. forname (classname). newinstance ();
// Create a car
ICF. makecar ();
// Handle exceptions
} Catch (incluentexception e ){
// Todo auto-generated Catch Block
System. Out. println ("this file cannot be found ...");
} Catch (instantiationexception e ){
// Todo auto-generated Catch Block
System. Out. println ("instantiation failed ...");
} Catch (illegalaccessexception e ){
// Todo auto-generated Catch Block
System. Out. println ("illegal access ...");
} Catch (classnotfoundexception e ){
// Todo auto-generated Catch Block
System. Out. println ("this class cannot be found ...");
}
}
} |
Program running result (console output)
|
Bydfactroy made a BYD for you |
Modify the configuration file factory. xml and change dynamic. Test. bydfactory to dynamic. Test. bmwfactory.
|
<Factory>
<! -- The full name of the corresponding car building factory class. Currently, the program can select Dynamic. Test. bmwfactory or dynamic. Test. bydfactory -->
<Factroy-Name> dynamic. Test. bmwfactory </factroy-Name>
</Factory> |
Run the program again to view the results (console output)
|
Bmwfactroy made a BMW for you |
We can see that the two running results are completely different, and we didn't modify any of the programs, but changed the configuration file! This is the advantage of the dynamic loading class, and it can also reduce the CPU and memory load.
The following is a reference article:
Recently, I wrote a mobile value-added project in Chengdu, where I am responsible for the backend server. The function is very simple. A mobile phone user opens a socket through GPRS to connect to the server, and I will respond based on the data transmitted by the user. Everyone who has done similar projects knows that a communication protocol similar to msnp needs to be defined first, but today's topic is how to design this system with high scalability. As this project has not conducted well-developed customer communication and demand analysis, there will certainly be many extensions in the future, and the communication protocols will surely become larger and larger, as a less diligent person, I certainly don't want to modify the program later, so this project is a good opportunity to practice object-oriented design.
First, define an interface to isolate the class:
Package org. bromon. Reflect;
Public interface operator
{
Public java. util. List Act (Java. util. List Params)
}
Based on the principle of the design pattern, we can write different classes for different functions. Each class inherits the operator interface. The client only needs to program the operator interface to avoid a lot of trouble. For example:
Package org. bromon. Reflect .*;
Public class success implements Operator
{
Public java. util. List Act (Java. util. List Params)
{
List result = new arraylist ();
Result. Add (new string ("operation successful "));
Return result;
}
}
We can also write many other classes, but there is a problem that the interface cannot be instantiated. We must manually control which class to instantiate. This is quite uncomfortable, if we can pass a parameter to the application, let ourselves choose to instantiate a class and execute its act method, then our work will be much easier.
Fortunately, I am using Java. Only Java provides such a reflection mechanism, or an introspection mechanism, to meet our unreasonable requirements. Compile a configuration file EMP. properties:
# Successful response
1000 = Success
# Sending common text messages to customers
2000 = Load
# The customer sends a common text message to the server
3000 = store
The key name in the file is the message header that the customer will send to me. If the customer sends 1000 to me, then I will execute the act Method of the success class. Similarly, if 2000 is sent to me, execute the act Method of the load class, so that the system fully complies with the open and closed principles. To add new functions, you do not need to modify the existing code, you only need to add the corresponding rules in the configuration file, write a new class, and implement the Act method. Even if I discard this project, it will be very scalable in the future. Such a system has excellent scalability and insertion ability.
The following example shows the function of dynamic loading. During execution, the program knows which class should be instantiated:
Package org. bromon. Reflect .*;
Import java. Lang. Reflect .*;
Public class testreflect
{
// Load the configuration file and query the class name corresponding to the Message Header
Private string loadprotocal (string header)
{
String result = NULL;
Try
{
Properties prop = new properties ();
Fileinputstream FCM = new fileinputstream ("EMP. properties ");
Prop. Load (FS );
Result = prop. getproperty (header );
FCM. Close ();
} Catch (exception E)
{
System. Out. println (E );
}
Return result;
}
// Respond to messages and import corresponding classes using reflection
Public String response (string header, string content)
{
String result = NULL;
String S = NULL;
Try
{
/*
* Import the property file EMP. properties to query the class name corresponding to the header.
* Matching classes are dynamically loaded using the reflection mechanism. All classes are isolated by the operator interface.
* You can extend the Protocol by modifying the attribute file and adding a new class (inheriting the msgoperator interface ).
*/
S = "org. bromon. Reflect." + this. loadprotocal (header );
// Load the class
Class C = Class. forname (s );
// Create a class example
Operator Mo = (operator) C. newinstance ();
// Construct the parameter list
Class Params [] = new class [1];
Params [0] = Class. forname ("Java. util. List ");
// Query the act Method
Method M = C. getmethod ("act", Params );
Object ARGs [] = new object [1];
ARGs [0] = content;
// Call the method and obtain the returned result
Object returnobject = M. Invoke (Mo, argS );
} Catch (exception E)
{
System. Out. println ("Handler-response:" + E );
}
Return result;
}
Public static void main (string ARGs [])
{
Testreflect TR = new testreflect ();
Tr. Response (ARGs [0], "message content ");
}
}
Test: Java testreflect 1000
This program is programmed for operator. Therefore, without any modifications, you can directly provide the load and store classes to support parameter calls in versions 2000 and 3000.
With this internal saving mechanism, the interface function can be played to the extreme, and the design model can also reflect the power.