I. Spring was born Spring is an open-source framework that is currently popular in the open-source community and is considered one of the most promising open-source frameworks. She was created by Rod Johnson to simplify enterprise-level system development. Spring has to say EJB, because Spring is a substitute for EJB in a sense. It is a lightweight container. Anyone who has used ejbs knows that ejbs are very complicated. For a simple function, you have to write multiple Java files and deployment files. It is a heavyweight container. Maybe you don't know about EJB. You may be unfamiliar with "light (heavy) Magnitude" and "Container". Here I will briefly introduce it. 1. What is a container? "The four friends of the" e-water-protected "and the" eye-catching "eye-pattern liquid mg" have been confused at the beginning. Specifically, containers are items that can be used to hold things. In the field of programming, it refers to the object used to install objects (OO idea. If you don't even know OO, we suggest you learn OO first. However, this object is special. It not only needs to accommodate other objects, but also maintains the relationship between objects. This may be too abstract. Let's look at a simple example: Code snippet 1:
public class Container { public void init() { Speaker s = new Speaker(); Greeting g = new Greeting(s); } } |
We can see that the Container class (Container) will generate a Speaker object and a Greeting object during initialization, and maintain their relationship. When the system uses these objects, ask the container directly. This is the most basic function of the container and maintains instances (objects) in the system ). If you are still confused here, don't worry. I will explain it later. 2. lightweight and heavyweight The so-called "heavyweight" is relative to "lightweight". It can also be said that "lightweight" is relative to "heavyweight. Before the emergence of Spring, enterprise-level development generally uses ejbs because the transaction management, declarative transaction support, persistence, and distributed computing provided by ejbs all simplify the development of enterprise-level applications. I put double quotation marks on "simplified", because this is relative. Heavyweight containers are intrusive. That is to say, you must use the functions provided by EJB in your code. For example, you must inherit an interface, declare a member variable. In this way, your code is bound to the EJB technology, and ejbs need container support such as JBOSS, so it is called "Heavyweight ". Relatively speaking, "lightweight" is non-intrusive. Classes in systems developed using Spring do not need to depend on classes in Spring, and container support is not required (of course, Spring itself is a container ), in addition, the size and running expenses of Spring are very small. In general, Spring is a better choice if the system does not require distributed computing or declarative transaction support. Ii. Several core concepts In my opinion, Spring has two core concepts: Reverse Control (IoC) and cross-section programming (AOP ). Another related concept is POJO, which I will also introduce. 1. POJO I have seen two full names of POJO: Plain Ordinary Java Object and Plain Old Java Object. The two are similar, meaning they are common Java classes. Therefore, you don't have to worry about who is right or who is wrong. POJO can be viewed as a simple JavaBean (class with a series of Getter and Setter methods ). It doesn't make much sense to strictly differentiate the concepts here. Just take a look. 2. IoC The full name of IoC is Inversion of Control. The reverse direction here is relative to that of EJB. EJB uses JNDI to find the desired object. It is active, while Spring injects the dependent object to the corresponding class (another concept "dependency injection" is involved here, which will be explained later ), is passive, so it is called "reverse ". Let's take a look at a piece of code. The difference here is easy to understand. Code snippet 2:
public void greet() { Speaker s = new Speaker(); s.sayHello(); } |
Code snippet 3:
public void greet() { Speaker s = (Speaker)context.lookup("ejb/Speaker"); s.sayHello(); } |
Code snippet 4:
public class Greeting { public Speaker s; public Greeting(Speaker s) { this.s = s; } public void greet() { s.sayHello(); } } |
We can compare the three pieces of code. Segment 2 does not use container encoding, segment 3 is EJB encoding, and segment 4 is Spring encoding. Combined with code snippet 1, can you see the advantages of Spring encoding? Maybe you will think that Spring encoding is the most complicated. But it doesn't matter. I will explain the benefits of Spring encoding later. Here I want to explain "dependency injection" first ". According to the example given by me, the Greeting class depends on the Speaker class. Both fragment 2 and fragment 3 actively obtain the Speaker, although they are obtained in different ways. However, segment 4 does not get or instantiate the Speaker class, but directly uses s in the greeting function. You may easily find that there is a s Injection in the constructor (You may usually use it as an input ). Where is the injection? Let's take a look at code snippet 1. This is the benefit of using containers to maintain dependencies between classes (generally, dependencies are injected using Setter instead of constructors, I am here to simplify the sample code ). Greeting does not need to care about where the Speaker came from or where it was obtained. Instead, it only needs to care about what it was about, that is, let the Speaker say a Greeting. 3. AOP The full name of AOP is Aspect-Oriented Programming, and Chinese translation is Aspect-Oriented or Aspect-Oriented Programming. You should be familiar with process-oriented programming and object-oriented programming, but it may be the first time you have heard of Aspect-Oriented Programming. In fact, these concepts sound very mysterious. In the end, they are just one sentence. Currently, systems tend to emphasize reducing the coupling between modules. The AOP technology is used to help achieve this goal. For example, if the above Greeting system contains the Log Module, security module, and transaction management module, each greet operation involves these three modules. Take the Log Module as an example, after each greet operation, you must record the greet content. For Speaker or Greeting objects, they do not know that their behaviors have been recorded. They still work as before, and there is no difference. The container only controls the log behavior. If you are confused here, it doesn't matter. You will understand it when talking about the specific Spring configuration and implementation. If we add a Valediction function to the Greeting system, the system structure of the AOP mode is as follows: GRETTING VALEDITION Log Security Transactions These modules run through the entire system and provide services for different functions of the system. Each module can be called as a "plane ". In fact, the "aspect" is an abstraction. It extracts the public behaviors of different parts of the system to form an independent module, and in a proper place (that is, the starting point, which will be explained later) insert the extracted functions into different parts of the system. From a certain point of view, the "aspect" is a very vivid description. It seems to be a cross-cutting tool on top of the system's functions. To continue the system's functions, you must first pass this aspect. These sections monitor and intercept system behaviors and execute additional tasks (such as logging) before or after some (specified) actions are executed ). The functional processes of the system (such as Greeting) do not know the existence of these aspects, but do not rely on these aspects, thus reducing the coupling between system modules. 3. Initial Spring experience In this section, I use a specific example Greeting to describe the general process and method of Spring development and the method of writing the Spring configuration file. First, create a Speaker class. You can think of this class as a POJO. Code snippet 5:
public class Speaker { public void sayHello() { System.out.println("Hello!"); } } |
Create a Greeting class. Code snippet 6:
public class Greeting { private Speaker speaker; public void setSpeaker(Speaker speaker) { this.speaker = speaker; } public void greet() { speaker.sayHello(); } } |
Create a Spring configuration file to associate these two classes. Code snippet 7 (applicationContext. xml ):
"1.0" encoding="UTF-8"?> "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <bean id="Speaker" class="Speaker"> <bean id="Greeting" class="Greeting"> <property name="speaker"> <ref bean="Speaker"/> |
To use Spring Framework, you must add the Spring package to Classpath. I use Eclipse + MyEclipse, which is automatically completed. We recommend that you use the Spring configuration file editor to edit the configuration file. It is easy to make mistakes by writing it manually. First, I will analyze the structure of the xml file and then perform a test. Start from the node and declare two. The second bean has a speaker attribute (property) that requires injection, and the injected content is another bean Speaker. The name here complies with the JavaBean specification. That is to say, if it is the speaker attribute, the Spring container will call setSpeaker () to inject this attribute. Indicates that another bean is referenced. The following is a simple test code: Code snippet 8:
public static void main(String[] args) { ApplicationContext context = New ClassPathXmlApplicationContext("applicationContext.xml"); Greeting greeting = (Greeting)context.getBean("Greeting"); greeting.greet(); } |
This code is very simple. If you have understood it in the previous article, there should be no problem here. It is worth noting that spring has two methods to create containers (we no longer use the container we wrote above), one is applicationcontext and the other is beanfactory. Applicationcontext is more powerful, and there is no big difference between the two. Therefore, applicationcontext is generally used. Spring containers help us maintain the beans declared in the configuration file and their dependencies. Our Beans only need to focus on their core business. Iv. Interface-Oriented Programming After reading so much, you may not think that spring has brought a lot of convenience to development. That's because the example I gave does not highlight the advantages of spring. Next I will show the strength of spring through interface programming. If you want to extend the greeting function, ask the speaker to greet him in different languages, that is, there are different speaker, such as chinesespeaker and englishspeaker. You will find it troublesome to modify the three encoding methods (code snippets 2, 3, and 4) mentioned above. If you want to join Spanish again next time, you have to repeat the work. Naturally, we will consider using an ispeaker interface to simplify the work. The changed code is as follows (the Code related to the interface is not listed here, and I think you should understand how to write it ): Code snippet 9:
public void greet() { ISpeaker s = new ChineseSpeaker(); s.sayHello(); } |
Code snippet 10:
public void greet() { ISpeaker s = (ISpeaker)context.lookup("ejb/ChineseSpeaker"); s.sayHello(); } |
Code snippet 11:
public class Greeting { public ISpeaker s; public Greet(ISpeaker s) { this.s = s; } public void greet() { s.sayHello(); } } |
By comparing the three pieces of code, you will find that the first method is to hard code the specific speaker into the code. The second method is slightly better, but it has not changed in essence, the third method is different, and the Code does not have information about the specific speaker. That is to say, if there are any changes next time, the greeting class of the third method does not need to be modified and compiled. According to the use of spring, you only need to modify the XML file to inject different speaker into greeting. Is the code extensibility much improved? There are many other things about spring interface programming that can be mined. Later I will introduce spring proxy interface programming. I will introduce so much here, if you are interested, you can go to Google for more information. 5. Apply the aspect in Spring Spring was born to support AOP. First, let's look at several concepts: 1. Aspect: a plane is a function module abstracted from the system. It has been described above. 2. Advice: notification is the specific implementation of the aspect. That is to say, what functions do you need to complete, and how to do it is done in the notification. This name may seem confusing and will be understood after reading the code. 3. Pointcut: The Pointcut defines where the notification should be applied to the system. Spring can only control methods (some AOP frameworks can control attributes). That is to say, you can choose to perform additional operations before or after method calls. 4. Target: the Target object is the notified object. It can be any class, including your own or third-party classes. With AOP, the target object only needs to focus on its core business. Other functions, such as logs, are supported by the AOP framework. 5. Proxy: in short, Proxy is the object generated after the notification is applied to the target object. Spring will generate a proxy object for each target object at runtime, and all future operations on the target object will be completed through the proxy object. Only in this way can the notification be redirected to the target object. For other parts of the system, this process is transparent, that is, it looks like no proxy. To simplify the process, I will only introduce these five concepts. Through these concepts, we should be able to understand the aspect programming of Spring. If you need to have a deep understanding of Spring AOP, it is also very quick to learn other concepts. The following uses an actual example to illustrate Spring's aspect programming. Continuing with the above Greeting example, we want to record that the Speaker was called before each Speaker. First, create a LogAdvice class: Code snippet 12:
public class LogAdvice implements MethodBeforeAdvice { public void before(Method arg0, Object[] arg1, Object arg2)throws Throwable { System.out.println("Speaker called!"); } } |
This involves a class, MethodBeforeAdvice, which is provided by the Spring class library and similar to AfterReturningAdvice, which can be understood literally. Don't rush to understand this class. I will explain it later. We will continue to look at how to apply this class to our system. Code snippet 13:
<bean id="Speaker" class="Speaker"/> <bean id="Greeting" class="Greeting"> <property name="speaker"> <ref bean="SpeakerProxy"/> <bean id="LogAdvice" class="LogAdvice"/> <bean id="SpeakerProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> ISpeaker <property name="interceptorNames"> LogAdvice <property name="target"> <ref local="Speaker"/> |
We can see that there are two more beans in our configuration file, one LogAdvice and the other SpeakerProxy. LogAdvice is simple. I will focus on SpeakerProxy. This Bean is actually implemented by the ProxyFactoryBean provided by Spring. The following defines three dependency injection attributes. 1. proxyInterfactes: This attribute defines the interfaces to be implemented by the Proxy, which can be one or multiple (if there are multiple interfaces, the list label should be used ). As I mentioned earlier, the Proxy is dynamically created during running, so this attribute tells Spring what interfaces are implemented when this Proxy is created. 2. interceptorNames: This attribute defines the notifications that the Proxy is redirected to. Here there is only one LogAdvice. 3. target: This attribute defines the objects to be proxies. In this example, target is Speaker. This definition actually limits that the objects to be proxies must implement an interface, which is a bit similar to the interface-Oriented Programming mentioned above. In fact, it can be understood that the interface definition can make other parts of the system unaffected. In the past, the ISpeaker interface was used to call the interface, and the Proxy is still the same. But actually the content is different. It used to be a Speaker, but now it is a Proxy. The target attribute allows the proxy to know where the specific method is implemented. Proxy can be seen as a packaging of target. Of course, Spring does not require interfaces. You can use CGLIB (an efficient code generation open-source class library) to directly generate subclasses based on the target object. However, this method is not recommended. We also tested our Greeting system as before, and the test code and code segment 8 were the same. The running result is as follows: Speaker called! Hello! See the results! In addition, you can find that the Log function has not changed the previous code or even the test code. This is the charm of AOP! We only changed the configuration file. The following explains the drop-down MethodBeforeAdvice. This class is not described in detail, because it involves another concept in Spring, "Jointpoint". I will introduce a before method in detail. This Method has three parameters: arg0, which indicates the vertex of the target object to be cut in. Since it is MethodBeforeAdvice, it is cut in before Method. Arg0 indicates the Method. The second parameter arg1 is the Method parameter, so the type is Object []. The third parameter is the target object. In the Greeting example, the arg2 type is actually a Speaker. In the Greeting example, we do not specify the methods of the target object to be switched in. Instead, all methods are called by default (although the Speaker only has one method ). You can use custom Pointcut to control the starting point. I will not introduce it here, because it does not affect understanding Spring AOP. If you are interested, you can simply google it. (Responsible editor: Yan Xun)
|