Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

The principle of Spring AOP implementation and how to apply CGLIB

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article is to share with you about the principle of Spring AOP implementation and how to carry out CGLIB applications. The editor thinks it is very practical, so I share it with you to learn. I hope you can get something after reading this article.

Introduction: AOP (Aspect Orient Programming), that is, aspect-oriented programming, as a supplement to object-oriented programming, is specially used to deal with cross-concerns distributed in various modules (different methods) in the system. In Java EE applications, AOP is often used to deal with some system-level services with crosscutting nature, such as transaction management, security check, cache, object pool management and so on. The key to the implementation of AOP lies in the AOP proxy automatically created by the AOP framework. AOP proxy is mainly divided into two categories: static proxy and dynamic proxy. Static proxy is represented by AspectJ, while dynamic proxy is represented by Spring AOP.

AOP (Aspect Orient Programming), as a supplement to object-oriented programming, is widely used to deal with some system-level services with crosscutting nature, such as transaction management, security check, cache, object pool management and so on. The key to the implementation of AOP lies in the AOP proxy automatically created by the AOP framework, and the AOP proxy can be divided into two categories: static proxy and dynamic proxy, in which static proxy is compiled using commands provided by the AOP framework, so that AOP proxy classes can be generated during the compilation phase, so it is also called compile-time enhancement. On the other hand, dynamic agents generate AOP dynamic proxy classes in memory "temporarily" at run time with the help of JDK dynamic agents, CGLIB, etc., so it is also called runtime enhancement.

The existence value of AOP

In traditional OOP programming, with objects as the core, the whole software system consists of a series of interdependent objects, which will be abstracted into classes and allow the use of class inheritance to manage general to special relationships between classes. With the increase of the scale of the software and the gradual upgrading of the application, some problems that are difficult to solve by OOP gradually appear.

We can analyze and abstract a series of objects with certain attributes and behaviors, and form a complete software function through the cooperation between these objects. Because objects can be inherited, we can abstract attributes with the same functions or characteristics into a hierarchical class structure. With the continuous expansion of software specifications, more and more specialization, and the continuous increase of OOP application practice, some problems that can not be solved well by OOP are exposed.

Now suppose there are three identical pieces of code in the system, which are usually completed by "copy" and "paste". The software developed by this "copy" and "paste" mode is shown in figure 1.

Figure 1. Software that contains the same code in multiple places

Looking at the diagram shown in figure 1, some readers may have found the shortcomings of this approach: if one day, the dark code snippet in figure 1 needs to be modified, do you want to open the code in three places to make changes? What if not 3 places contain this code, but 100 or even 1000 places contain this code segment?

To solve this problem, we usually define the dark part of the code shown in figure 1 as a method, and then call the method in three code snippets. In this way, the structure of the software system is shown in figure 2.

Figure 2 realizes the system function through method call

For the software system shown in figure 2, if you need to modify the dark part of the code, you only need to modify one place, no matter how many places the method is called in the whole system, the program does not need to modify these places. only need to modify the called method-in this way, the complexity of software maintenance is greatly reduced.

For methods 1, 2, and 3 shown in figure 2, dark methods still need to be explicitly called, which can solve most application scenarios. But for some more special cases: the application requires methods 1, 2, 3 to be completely separated from dark methods-methods 1, 2, and 3 do not need to call dark methods directly, so how to solve it?

Because the software system requirements change very frequently, only the core business functions are realized in the early design method 1, method 2, and method 3. After a period of time, we need to add transaction control for method 1, method 2, and method 3. After another period of time, the customer proposes that methods 1, 2 and 3 need to be verified by users, and only legitimate users can implement these methods. After another period of time, the customer proposed that method 1, method 2, method 3 should add log records; after another period of time, the customer also proposed …... In the face of such a situation, what should we do? There are usually two ways to do this:

According to the requirement statement, reject the customer request directly; embrace the demand and meet the customer's demand.

The practice is obviously not good. The customer is God, and we should try our best to meet the needs of our customers. The second approach is usually adopted, so how to solve it? Do you define a new method at a time, and then modify method 1, method 2, and method 3 to add new methods to be called? It's a lot of work to do. We want a special method: as long as we define the method, there is no need to explicitly call it in method 1, method 2, and method 3, and the system will "automatically" execute the special method.

The above idea sounds magical, even some impractical, but it is actually completely achievable, and the technology to achieve this requirement is AOP. AOP is specially used to deal with the problem of cross-concern distributed in various modules (different methods) in the system. In Java EE applications, AOP is often used to deal with some system-level services with crosscutting nature, such as transaction management, security check, cache, object pool management and so on. AOP has become a very common solution.

Using compile-time enhancements of AspectJ for AOP

AspectJ is an AOP framework based on Java language, which provides powerful AOP functions. Many other AOP frameworks draw lessons from or adopt some of these ideas.

AspectJ is an AOP implementation of Java language, which mainly consists of two parts: * parts define how to express and define syntax specifications in AOP programming, through this set of language specifications, we can easily use AOP to solve the cross-concern problems in Java language; the other part is tools, including compilers, debugging tools and so on.

AspectJ is one of the earliest and powerful AOP implementations, which has a good implementation of the whole set of AOP mechanisms. AOP implementations in many other languages also draw lessons from or adopt many designs in AspectJ. In the Java domain, many of the syntax structures in AspectJ have basically become the standard in the AOP domain.

It is relatively easy to download and install AspectJ. Readers can log on to the AspectJ official website (http://www.eclipse.org/aspectj) to download an executable JAR package. Use the java-jar aspectj-1.x.x.jar command and click the "Next" button several times to successfully install AspectJ.

After you have successfully installed AspectJ, you will see the following file structure under the E:\ Java\ AOP\ aspectj1.6 path (the installation path for AspectJ):

Bin: aj, aj5, ajc, ajdoc, ajbrowser and other commands are stored in this path, of which the ajc command is the most commonly used. Its function is similar to javac and is used to enhance ordinary Java classes at compile time.

Docs: this path stores AspectJ instructions, reference manuals, API documents, and other documents.

Lib: the four JAR files in this path are the core class libraries of AspectJ.

Relevant authorization documents.

Some documents and introductory books on AspectJ think that you must use the Eclipse tool when it comes to using AspectJ, and it seems that you can't use AspectJ without the tool.

Although AspectJ is an open source project of the Eclipse Foundation and provides Eclipse's AJDT plug-in (AspectJ Development Tools) to develop AspectJ applications, AspectJ absolutely does not have to rely on Eclipse tools.

In fact, the use of AspectJ is very simple, just as we use JDK to compile and run Java programs. Let's demonstrate the use of AspectJ through a simple program and analyze how AspectJ can be enhanced at compile time.

First write a simple Java class, which is used to simulate a business component, the Java class.

List 1.Hello.java

Public class Hello {/ / defines a simple method to simulate the business logic method public void sayHello () {System.out.println ("Hello AspectJ!") in the application;} / / main method, the entry of the program public static void main (String [] args) {Hello h = new Hello (); h.sayHello ();}}

The above Hello class simulates a business logic component, compiles and runs the Java program, and there is no suspense about the result. The program will print the "Hello AspectJ" string on the console.

Assuming that the customer now needs to start the transaction before executing the sayHello () method and close the transaction when the method execution finishes, in traditional programming mode, we have to manually modify the sayHello () method-- if we use AspectJ instead, we don't have to modify the sayHello () method above.

Let's define a special Java class.

List 2.TxAspect.java

Public aspect TxAspect {/ / specifies that the following code block void around () is executed when the Hello.sayHello () method is executed: call (void Hello.sayHello ()) {System.out.println ("start transaction..."); proceed (); System.out.println ("transaction end...");}}

Readers may have found that instead of using class, interface, and enum to define Java classes in the above class files, they use aspect-is there a new keyword in the Java language? No! The TxAspect above is not a Java class at all, so aspect is not a keyword supported by Java, it's just a keyword that AspectJ can recognize.

The above bold code is not a method either, it just specifies that when the program executes the sayHello () method of the Hello object, the system will instead execute the curly braces code block of the bold code, where proceed () represents the callback of the original sayHello () method.

As mentioned earlier, Java does not recognize the contents of the TxAspect.java file, so we will use the ajc.exe command to compile the above Java program. In order to be able to use the ajc.exe command on the command line, you need to add the bin path under the AspectJ installation directory (such as the E:\ Java\ AOP\ aspectj1.6\ bin directory) to the system's PATH environment variable. Next, execute the following command to compile:

Ajc-d. Hello.java TxAspect.java

We can think of ajc.exe as a javac.exe command, which is used to compile Java programs. The difference is that the ajc.exe command recognizes the syntax of AspectJ; in this sense, we can think of ajc.exe as an enhanced version of the javac.exe command.

There is still no change to run the Hello class, because the Hello class is under the lee package. The program runs the Hello class with the following command: java lee.Hello

Run the program and you will see an amazing result:

Start the business...

Hello AspectJ!

The transaction ends...

From the results of the above run, we can see that we can not make any changes to the Hello.java class, and at the same time meet the needs of customers: the above program just prints "start transaction" on the console. , "end the transaction..." To simulate the transaction operation, in fact, we can use the actual transaction operation code to replace these two lines of simple statements, which can meet the needs of customers.

If the customer puts forward a new requirement again and needs to add the logging function after the sayHello () method, it is also very simple. Let's define another LogAspect as follows:

List 3.LogAspect.java

Public aspect LogAspect {/ / defines a PointCut named logPointcut / / the PointCut corresponds to the sayHello method pointcut logPointcut (): execution (void Hello.sayHello ()) of the specified Hello object; / / executes the following code block after () after logPointcut: logPointcut () {System.out.println ("logging...");}}

The bold code of the above program defines a Pointcut:logPointcut, which is equivalent to executing the sayHello () method of the Hello object, and specifies that a simple block of code is executed after logPointcut, that is, the specified block of code is executed after the sayHello () method. Use the following command to compile the above Java program: ajc-d. * .java

Run the Hello class again, and you will see the following run result:

Start the business...

Hello AspectJ!

Keep a log...

The transaction ends...

Judging from the results of the above run, we can continue to add new functionality to the sayHello () method by using the AOP support provided by AspectJ.

Why is it that without any changes to the Hello class, the Hello class can constantly and dynamically add new functionality? This doesn't seem to conform to the basic grammar rules of Java. In fact, we can use Java's decompilation tool to decompile the Hello.class file generated by the previous program, and find that the code of the Hello.class file is as follows:

List 4.Hello.class

Package lee; import java.io.PrintStream; import org.aspectj.runtime.internal.AroundClosure; public class Hello {public void sayHello () {try {System.out.println ("Hello AspectJ!");} catch (Throwable localThrowable) {LogAspect.aspectOf (). Ajc$after$lee_LogAspect$1 $9fd5dd97 (); throw localThrowable;} LogAspect.aspectOf (). Ajc$after$lee_LogAspect$1 $9fd5dd97 ();}. Private static final void sayHello_aroundBody1 $advice (Hello target, TxAspect ajc$aspectInstance, AroundClosure ajc$aroundClosure) {System.out.println ("start transaction..."); AroundClosure localAroundClosure = ajc$aroundClosure; sayHello_aroundBody0 (target); System.out.println ("transaction ends...");}}

It is not difficult to find that this Hello.class file is not compiled from the original Hello.java file, and a lot of new content has been added to the Hello.class-which indicates that AspectJ compiles a new class "automatically" at compile time, which enhances the functionality of the original Hello.java class, so AspectJ is often referred to as the compile-time enhanced AOP framework.

Tip: as opposed to AspectJ, there is another AOP framework that does not need to enhance the target class at compile time, but instead generates a proxy class of the target class at run time, which either implements the same interface as the target class or is a subclass of the target class-in short, an instance of the proxy class can be used as an instance of the target class. In general, the compile-time enhanced AOP framework has a performance advantage-- because the runtime dynamically enhanced AOP framework requires dynamic enhancement at each run time.

In fact, AspectJ allows you to add new functionality to multiple methods at the same time, as long as we specify more matching methods when we define the Pointcut. The following snippet:

Pointcut xxxPointcut (): execution (void Hand.say* ())

The xxxPointcut in the above program will be able to match all methods that begin with H and start with say, but the method must return void;. If you do not want to match any return value type, you can change the code to the following form:

Pointcut xxxPointcut (): execution (* Hang.say* ()); xxxPointcut ()

For information about how to define Aspect, Pointcut, etc., in AspectJ, you can refer to the quick5.pdf file in the doc directory under the AspectJ installation path.

Use Spring AOP

Like AspectJ, Spring AOP also needs to enhance the target class, that is, to generate a new AOP proxy class; unlike AspectJ, Spring AOP does not need to use any special commands to compile the Java source code, it generates the AOP proxy dynamically and temporarily in memory at run time.

Spring allows the use of AspectJ Annotation to define aspects (Aspect), pointcut (Pointcut), and enhancement processing (Advice), and the Spring framework can identify and generate AOP proxies based on these Annotation. Spring only uses the same annotations as AspectJ 5, but does not use AspectJ's compiler or Weaver. The bottom layer still uses Spring AOP, still dynamically generates AOP proxies at run time, and does not rely on AspectJ's compiler or weaver.

To put it simply, Spring still enhances the target object by generating dynamic proxies at run time, so it does not require additional compilation or AspectJ weaver support; while AspectJ is enhanced at compile time, AspectJ needs its own compiler to compile Java files, as well as a weaver.

To enable Spring's support for @ AspectJ aspect configuration and to ensure that the target Bean in the Spring container is automatically enhanced by one or more aspects, the following snippets must be configured in the Spring configuration file:

Of course, if we want to fully enable Spring's Zero configuration feature, we also need to enable Spring's Zero configuration support to let Spring automatically search for Bean classes under the specified path.

The so-called automatic enhancement means that Spring will judge whether one or more aspects need to enhance the specified Bean, and automatically generate the corresponding proxy accordingly, so that the enhancement process is called at the appropriate time.

If you do not intend to use Spring's XML Schema configuration, you should add the following snippet to the Spring configuration file to enable @ AspectJ support.

The AnnotationAwareAspectJAutoProxyCreator in the above configuration file is a Bean post-processor (BeanPostProcessor) that will generate an AOP proxy for the Bean in the container

When the @ AspectJ support is enabled, as long as we configure a Bean,Spring with the @ Aspect annotation in the Spring container, the Bean is automatically recognized and the Bean is treated as an aspect Bean.

Configuring aspect Bean (that is, Bean with @ Aspect annotation) in the Spring container is no different from configuring ordinary Bean. It uses elements to configure and supports dependency injection to configure attribute values. If we enable the "zero configuration" feature of Spring, we can also let Spring automatically search and load the aspect Bean under the specified path.

Use @ Aspect to annotate a Java class, which will be the aspect Bean, as shown in the following code snippet:

/ / use @ Aspect to define an aspect class @ Aspect public class LogAspect {/ / define other contents of this class.}

Aspect classes (classes decorated with @ Aspect) can have methods, attribute definitions, and possibly pointcuts and enhanced processing definitions like other classes.

When we decorate a Java class with @ Aspect, Spring will not treat the Bean as a component Bean, so the post-processing Bean responsible for automatic enhancement will skip the Bean and will not make any enhancements to the Bean.

Developers do not have to worry about enhancements to aspect classes defined using @ Aspect. When the Spring container detects that a Bean class uses the @ Aspect annotation, the Spring container does not enhance the Bean class.

The following will consider using Spring AOP to overwrite the example described earlier:

The following example uses a simple Chinese class to simulate business logic components:

List 5.Chinese.java

@ Component public class Chinese {/ / implement the sayHello () method public String sayHello (String name) of the Person interface {System.out.println ("--executing sayHello method--"); / / returns the simple string return name + "Hello, Spring AOP" } / / define an eat () method public void eat (String food) {System.out.println ("I'm eating:" + food);}}

After providing the above Chinese class, assume that you also need to add transaction control and logging to each method of the above Chinese class, and you can consider using Around and AfterReturning enhancements.

First take a look at the AfterReturning enhancement processing code.

List 6.AfterReturningAdviceTest.java

/ / define an aspect @ Aspect public class AfterReturningAdviceTest {/ / matches the execution of all classes and / / all methods under the org.crazyit.app.service.impl package as the pointcut @ AfterReturning (returning= "rvt", pointcut= "execution (* org.crazyit.app.service.impl.*.* (..)")) Public void log (Object rvt) {System.out.println ("get the return value of the target method:" + rvt); System.out.println ("Analog logging function.");}}

The above Aspect class is decorated with @ Aspect so that Spring treats it as an aspect Bean. The bold code in the program specifies that the log (Object rvt) method will be woven into the log (Object rvt) method after calling all methods of all classes under the org.crazyit.app.service.impl package.

Take a look at the Around enhanced processing code:

List 7.AfterReturningAdviceTest.java

/ / define an aspect @ Aspect public class AroundAdviceTest {/ / matches the execution of all classes and / / all methods under the org.crazyit.app.service.impl package as the pointcut @ Around ("execution (* org.crazyit.app.service.impl.*.* (..)") Public Object processTx (ProceedingJoinPoint jp) throws java.lang.Throwable {System.out.println ("Simulation starts the transaction before executing the target method"); / / executes the target method and saves the return value Object rvt = jp.proceed (new String [] {"changed parameters"}) after the target method is executed; System.out.println ("after the target method is executed, the simulation ends the transaction.") Return rvt + "what's new";}}

Similar to the previous AfterReturning enhancement, @ Aspect is also used to modify the previous Bean, where the bold code specifies that the "Around" of all methods of all classes under the org.crazyit.app.service.impl package is woven into the processTx (ProceedingJoinPoint jp) method

It should be pointed out that although only AfterReturning and Around enhancements of Spring AOP are introduced here, Spring also supports Before, After, AfterThrowing and other enhanced processing. For more and more detailed programming details on Spring AOP programming, you can refer to the book "lightweight Java EE Enterprise Application practice".

This example uses the zero configuration of Spring to enable Spring AOP, so the above Chinese class uses the @ Component modifier, while the aspect Bean uses the @ Aspect modifier, and the Advice in the aspect Bean uses the @ AfterReturning and @ Around modifiers, respectively. Next, all you need to do is provide the following configuration file for Spring:

List 8.bean.xml

Next, get the chinese Bean in the Spring container in the traditional way, and call the two methods of the Bean. The program code is as follows:

List 9.BeanTest.java

Public class BeanTest {public static void main (String [] args) {/ / create Spring container ApplicationContext ctx = new ClassPathXmlApplicationContext ("bean.xml"); Chinese p = ctx.getBean ("chinese", Chinese.class); System.out.println (p.sayHello ("Zhang San")); p.eat ("watermelon");}}

As can be seen from the above development process, there is nothing special about the business components and aspect Bean provided by developers for Spring AOP. It's just that aspect Bean needs to be decorated with @ Aspect. The program does not need to use special compilers and weavers for processing.

Run the above program and you will see the following execution result:

Before executing the target method, the simulation starts the transaction.

-executing sayHello method-

After the target method is executed, the simulation ends the transaction.

Get the return value of the target method: the changed parameter Hello, the new content of Spring AOP

Analog logging function.

The changed parameter Hello, the new content of Spring AOP

Before executing the target method, the simulation starts the transaction.

I'm eating: changed parameters

After the target method is executed, the simulation ends the transaction.

Get the return value of the target method: what's new in null

Analog logging function.

Although the program is calling the sayHello and eat methods of the Chinese object, it is not difficult to see from the above running results that what is actually executed is not the method of the Chinese object, but the method of the AOP proxy. That is, Spring AOP also generates an AOP proxy class for the Chinese class. This can be seen by adding the following code to the program: System.out.println (p.getClass ())

The above code can output the implementation class of the object referenced by the p variable. If you execute the program again, you can see that the above code produces the output of class org.crazyit.app.service.impl.Chinese$$EnhancerByCGLIB$$290441d2. This is the implementation class of the object referenced by the p variable, which is the AOP proxy class dynamically generated by Spring AOP. As you can see from the class name of the AOP proxy class, the AOP proxy class is generated by CGLIB.

If you modify the above program slightly: just let the above business logic class Chinese class implement an arbitrary interface-this is more in line with the "interface-oriented programming" principle advocated by Spring. Suppose the program provides the following Person interface for the Chinese class and lets the Chinese class implement the interface:

List 10.Person.java

Public interface Person {String sayHello (String name); void eat (String food);}

Next, let the BeanTest class program against the Person interface instead of the Chinese class. Change the BeanTest class to the following form:

List 11.BeanTest.java

Public class BeanTest {public static void main (String [] args) {/ / create Spring container ApplicationContext ctx = new ClassPathXmlApplicationContext ("bean.xml"); Person p = ctx.getBean ("chinese", Person.class); System.out.println (p.sayHello ("Zhang San")); p.eat ("watermelon"); System.out.println (p.getClass ());}}

The original program is oriented to Chinese class programming, now the program is changed to Person interface programming, run the program again, the result of the program has not changed. Just System.out.println (p.getClass ()); will output class $Proxy7, which means that the AOP agent at this time is not generated by CGLIB, but by the JDK dynamic agent.

The principle of the Spring AOP framework for dealing with the AOP proxy class is: if the implementation class of the target object implements the interface, Spring AOP will use JDK dynamic proxy to generate the AOP proxy class; if the implementation class of the target object does not implement the interface, Spring AOP will use CGLIB to generate the AOP proxy class-but this selection process is completely transparent to developers and developers do not need to care.

Spring AOP dynamically chooses to use JDK dynamic proxy and CGLIB to generate AOP proxy. If the target class implements the interface, Spring AOP does not need the support of CGLIB, but directly uses Proxy and InvocationHandler provided by JDK to generate AOP proxy. How to generate dynamic proxies with Proxy and InvocationHandler is beyond the scope of this article, and readers who are interested in the use of Proxy and InvocationHandler can refer to the Java API documentation or the Crazy Java handouts.

Analysis of the principle of Spring AOP

As you can see from the previous introduction, the AOP agent is actually an object dynamically generated by the AOP framework, which can be used as a target object. The AOP proxy contains all the methods of the target object, but the methods in the AOP proxy are different from those of the target object: the AOP method adds enhanced processing at a specific pointcut and calls back the methods of the target object.

The schematic diagram of the methods and target objects contained in the AOP agent is shown in figure 3.

The method of figure 3.AOP agent and the method of target object

Spring AOP implementation principle and CGLIB Application

Spring's AOP substitute reason Spring's IoC container is responsible for generating and managing, and its dependencies are also managed by the IoC container. Therefore, the AOP agent can directly use other Bean instances in the container as targets, and this relationship can be provided by the dependency injection of the IoC container.

Throughout AOP programming, there are only three parts in which programmers are required to participate:

● defines common business components.

● defines a pointcut, which may crosscut multiple business components.

● defines enhanced processing, which is the processing actions woven into common business components in the AOP framework.

The * * parts of the above three parts are the most common things and do not need to be explained in detail. Then the key to AOP programming is to define pointcuts and define enhanced processing. Once the appropriate pointcut and enhancement processing are defined, the AOP framework automatically generates an AOP proxy, and the method of the AOP proxy is roughly as follows:

Method of proxy object = enhanced processing + method of proxied object

In the above business definition, it is not difficult to find that the implementation principle of Spring AOP is actually very simple: the AOP framework is responsible for generating the AOP proxy class dynamically, and the methods of this proxy class consist of Advice and methods that call back the target object.

For the previously mentioned software call structure shown in figure 2: when method 1, method 2, method 3 …... When you need to call a method with a "crosscutting" nature, the traditional practice is for the programmer to manually modify method 1, method 2, method 3. This "crosscutting" method is called through the code, but it is not extensible because the code has to be changed every time.

So the AOP framework appears, and the AOP framework can "dynamically" generate a new proxy class, which contains methods 1, 2, 3. Calls to this method with a "crosscutting" nature are also added-but this invocation is handled by a proxy class automatically generated by the AOP framework, so it is extremely extensible. Programmers do not need to manually modify the code of method 1, method 2, and method 3. Programmers only need to define the pointcut-the AOP proxy class generated by the AOP framework contains the new method 1, access 2, and method 3. According to the pointcut, the AOP framework will decide whether to call back the method with the nature of "crosscutting" in method 1, method 2, and method 3.

In short: the secret of the AOP principle is that the proxy class is generated dynamically, which implements the invocation of figure 2-- which does not require the programmer to modify the code. The next CGLIB is a proxy generation library, and here's how to use CGLIB to generate proxy classes.

Generate proxy classes using CGLIB

CGLIB (Code Generation Library), in a nutshell, is a code generation library. It can dynamically generate a subclass of a class at run time.

Using the previously defined Chinese class, we now use CGLIB directly to generate the proxy, which can also achieve the same effect as the Spring AOP proxy.

Let's first provide an interceptor implementation class for CGLIB:

List 12.AroundAdvice.java

Public class AroundAdvice implements MethodInterceptor {public Object intercept (Object target, Method method, Object [] args, MethodProxy proxy) throws java.lang.Throwable {System.out.println ("simulate starting a transaction before executing the target method"); / / execute the target method and save the return value Object rvt = proxy.invokeSuper (target, new String [] {"changed parameters"}) after the target method is executed System.out.println ("simulation ends the transaction after executing the target method"); return rvt + "what's new";}}

The above AroundAdvice.java works like the AroundAdvice described earlier. It can be woven into the enhanced processing before and after the target method is called.

Next, the program provides a ChineseProxyFactory class, which generates a proxy class for Chinese through CGLIB:

List 13.ChineseProxyFactory.java

Public class ChineseProxyFactory {public static Chinese getAuthInstance () {Enhancer en = new Enhancer (); / / set the target class en.setSuperclass (Chinese.class) to proxy; / / set the interceptor en.setCallback (new AroundAdvice ()) to be proxied; / / generate an instance of the proxy class return (Chinese) en.create ();}}

The above bold code is the key code to generate the proxy object using CGLIB's Enhancer. At this time, the Enhancer will take the Chinese class as the target class and the AroundAdvice object as the "Advice". The program will generate a subclass of Chinese, which is the CGLIB generation proxy class, which can be used as a Chinese object, but it enhances the methods of the Chinese class.

The main program to test the Chinese proxy class is as follows:

List 14.Main.java

Public class Main {public static void main (String [] args) {Chinese chin = ChineseProxyFactory.getAuthInstance (); System.out.println (chin.sayHello ("Sun WuKong")); chin.eat ("watermelon"); System.out.println (chin.getClass ());}}

Run the above main program and see the following output:

Before executing the target method, the simulation starts the transaction.

-executing sayHello method-

After the target method is executed, the simulation ends the transaction.

The changed parameter Hello, the new content of CGLIB

Before executing the target method, the simulation starts the transaction.

I'm eating: changed parameters

After the target method is executed, the simulation ends the transaction.

Class lee.Chinese$$EnhancerByCGLIB$$4bd097d9

Judging from the output above, the proxy generated by CGLIB can be used as a Chinese object, and the sayHello () and eat () methods of the CGLIB proxy object have added transaction control (just simulation). This CGLIB proxy is actually the AOP proxy generated by Spring AOP.

Through the output of the program * *, it is not difficult to find that the implementation class of this proxy object is lee.Chinese$$EnhancerByCGLIB$$4bd097d9, which is the proxy class generated by CGLIB, and the format of this proxy class is exactly the same as that of the proxy class generated by Spring AOP.

This is the essence of Spring AOP: Spring AOP dynamically generates a proxy object through CGLIB, which is called an AOP proxy, and the AOP proxy method completes the enhancement of the target method by dynamically weaving enhancement processing at the pointcut of the target object.

AOP is widely used to deal with some system-level services with crosscutting nature. The emergence of AOP is a good supplement to OOP, which enables developers to deal with crosscutting services in a more elegant way. No matter what kind of AOP implementation, whether AspectJ or Spring AOP, they all need to generate an AOP proxy class dynamically, except that the timing of generating the AOP proxy class is different: AspectJ generates the AOP proxy class at compile time, so it has better performance, but it needs to be processed with a specific compiler, while Spring AOP uses runtime to generate the AOP proxy class, so there is no need to use a specific compiler for processing. Because Spring AOP needs to generate AOP proxies each time it runs, the performance is slightly worse.

The above is the principle of Spring AOP implementation and how to apply CGLIB. The editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report