Cainiao SSH (14th) -- implementation principle of Spring container AOP -- Dynamic proxy and sshaop

Source: Internet
Author: User

Cainiao SSH (14th) -- implementation principle of Spring container AOP -- Dynamic proxy and sshaop

I wrote a blog about IOC-parsing and simple implementation of Spring container IOC. I will talk about AOP today. We all know that the two major features of Spring are IOC and AOP.


IOC is responsible for dynamically injecting objects into the container to achieve the effect of injecting objects to the container whenever and whenever needed, go. Think about it. If you have the same skills in real life, it will be cool. As for how cool it is, make up your own brain. What about AOP, what it implements is another major benefit of the container, that is, the objects in the container can enjoy the public services in the container. So how does the container do it? How can an object in it automatically own the public services it provides? The answer is what we will discuss today-dynamic proxy.


Dynamic proxy is nothing new. People who have learned the design mode should know the proxy mode. The proxy mode is a static proxy, dynamic proxy uses reflection and dynamic compilation to change the proxy mode to dynamic. The principle is similar to dynamic injection. during compilation, the Agent Mode determines who the agent class is going to proxy, and the dynamic agent knows who it is going to proxy when it is running.


Spring has two types of dynamic proxies: one is JDK's dynamic proxy, and the other is cglib dynamic proxy (by modifying the bytecode to implement proxy ). Today, we will mainly discuss how JDK dynamic proxy works. The JDK proxy method is mainly implemented through reflection and dynamic compilation. Let's use the code to see how it is implemented.


Suppose we want to proxy the following user management:

// User management interface package com. tgb. proxy; public interface UserMgr {void addUser (); void delUser () ;}// package com. tgb. proxy; public class UserMgrImpl implements UserMgr {@ Overridepublic void addUser () {System. out. println ("add user ..... ") ;}@ Overridepublic void delUser () {System. out. println ("delete a user ..... ");}}

According to the proxy mode, a proxy class must be used to implement the UserMgr interface, declare a UserMgrImpl in it, and then call the addUser and delUser methods respectively, add the other operations we need before and after the call. But this is clearly all written to death. How can we achieve dynamic performance? Don't worry. Let's take a look.

We know that to implement proxy, both our proxy class and the proxy class must implement the same interface, but dynamic proxy does not know who we are going to proxy, I don't know which interface we want to implement. What should I do? We only need to know who to proxy before providing the corresponding proxy class. Why don't we wait to know who to proxy and then generate another proxy class? The solution is to dynamically generate the proxy class!


At this time, our dear reflection is useful again. We can write a method to receive the proxy class, in this way, we can know all its information through reflection-including its type, its method, and so on (if you do not know how to get it, please first check out my reflection blog reflection 1 and reflection 2.)


The two cores of JDK dynamic Proxy are InvocationHandler and Proxy. Below we use simple code to simulate how they are implemented:


InvocationHandler interface:

package com.tgb.proxy;import java.lang.reflect.Method;public interface InvocationHandler {public void invoke(Object o, Method m);}


The key part of implementing dynamic Proxy is to dynamically generate our specific Proxy class through Proxy:

Package com. tgb. proxy; import java. io. file; import java. io. fileWriter; import java. lang. reflect. constructor; import java. lang. reflect. method; import java.net. URL; import java.net. URLClassLoader; import javax. tools. javaCompiler; import javax. tools. standardJavaFileManager; import javax. tools. toolProvider; import javax. tools. javaCompiler. compilationTask; public class Proxy {/*** @ param infce interface of the Proxy Class * @ param h Proxy class * @ return * @ throws Exception */public static Object newProxyInstance (Class infce, invocationHandler h) throws Exception {String methodStr = ""; String rt = "\ r \ n"; // obtain all infce Methods Using Reflection, and re-assemble Method [] methods = infce. getMethods (); for (Method m: methods) {methodStr + = "@ Override" + rt + "public" + m. getReturnType () + "" + m. getName () + "() {" + rt + "try {" + rt + "Method md =" + infce. getName () + ". class. getMethod (\ "" + m. getName () + "\"); "+ rt +" h. invoke (this, md); "+ rt +"} catch (Exception e) {e. printStackTrace () ;}" + rt + "}" + rt ;}// generate the Java source file String srcCode = "package com. tgb. proxy; "+ rt +" import java. lang. reflect. method; "+ rt +" public class $ Proxy1 implements "+ infce. getName () + "{" + rt + "public $ Proxy1 (InvocationHandler h) {" + rt + "this. h = h; "+ rt +"} "+ rt +" com. tgb. proxy. invocationHandler h; "+ rt + methodStr + rt +"} "; String fileName =" d:/src/com/tgb/proxy/$ Proxy1.java "; file f = new File (fileName); FileWriter fw = new FileWriter (f); fw. write (srcCode); fw. flush (); fw. close (); // compile the Java file into the class file JavaCompiler compiler = ToolProvider. getSystemJavaCompiler (); StandardJavaFileManager fileMgr = compiler. getStandardFileManager (null, null, null); Iterable units = fileMgr. getJavaFileObjects (fileName); CompilationTask t = compiler. getTask (null, fileMgr, null, units); t. call (); fileMgr. close (); // load to memory and instantiate URL [] urls = new URL [] {new URL ("file:/" + "d: /src/")}; URLClassLoader ul = new URLClassLoader (urls); Class c = ul. loadClass ("com. tgb. proxy. $ Proxy1 "); Constructor ctr = c. getConstructor (InvocationHandler. class); Object m = ctr. newInstance (h); return m ;}}

The main function of this class is to dynamically assemble a proxy class based on the information of the proxy object, generate the $ Proxy1.java file, and compile it into $ Proxy1.class. In this way, we can generate the expected proxy class based on the specific proxy object. In this way, we do not need to know who we want to represent in advance. That is to say, we will generate a proxy class for you who you want to represent and what kind of proxy you want.


Then, on the client, we can perform proxy at will.

Package com. tgb. proxy; public class Client {public static void main (String [] args) throws Exception {UserMgr mgr = new UserMgrImpl (); // Add transaction processing for user management InvocationHandler h = new TransactionHandler (mgr); UserMgr u = (UserMgr) Proxy. newProxyInstance (UserMgr. class, h); // added the function TimeHandler h2 = new TimeHandler (u); u = (UserMgr) Proxy for user management. newProxyInstance (UserMgr. class, h2); u. addUser (); System. out. println ("\ r \ n =========== gorgeous split line =============\ r \ n"); u. delUser ();}}


Running result:

Start Time: October 22,-October 15: 48: 54 seconds start transaction ..... add a user ..... commit a transaction ..... end Time: October 22,-October 15: 48: 57 seconds elapsed time: 3 seconds ============== gorgeous split line ============ Start Time: January 1, 2014-January 15, July: 48 minutes: enable transaction in 57 seconds ..... delete a user ..... commit a transaction ..... end Time: October 11,-October 15: seconds time: 3 seconds

Here I have written two proxy functions, one is transaction processing, and the other is the proxy that shows the method execution time. Of course, they are all very simple writing, just to illustrate this principle. Of course, we can write the AOP to the configuration file like Spring, because the previous article has already written how to inject it through the configuration file, so we will not repeat it here.

At this point, you may have a question: As you mentioned above, as long as the objects in the container are put, there will be container public services. Why didn't I see them? Okay, let's continue to look at our proxy functions:


Transaction processing:

Package com. tgb. proxy; import java. lang. reflect. method; public class TransactionHandler implements InvocationHandler {private Object target; public TransactionHandler (Object target) implements super(%%%this.tar get = target;} @ Overridepublic void invoke (Object o, Method m) {System. out. println ("enable transaction ..... "); try {m. invoke (target);} catch (Exception e) {e. printStackTrace ();} System. out. println ("commit a transaction ..... ");}}

From the Code, it is not difficult to see that our proxy function does not involve any specific information of the objects to be proxies. What are the advantages of this? The advantage is that the proxy is completely separated from the objects to be proxy, so that we can freely combine the proxy and the objects to be proxy. In other words, we only need one function. There is only one function. Isn't this function a public function? Regardless of the number of objects in the container, you can enjoy the services provided by the container. This is the benefit of containers.


I don't know what I'm talking about. You are welcome to discuss it actively.



Principles of declarative transactions using Spring AOP proxy

First, inject sessionFactory into HibernateTransactionManager, and then inject the HibernateTransactionManager object into the TransactionProxyFactoryBean object ~ There should be another definition of sessionFactory.

AOP is a proxy-oriented model. Originally, an application must operate on an object, but this object contains a lot of business logic unrelated to itself, not as good as logs and locks. So we need to find a way to extract all these irrelevant things out. The extracted object is the proxy object.

When the application calls the proxy object again, it will call the proxy object, which contains the call to the proxy object and the unrelated business logic method that is extracted. Proxy objects are purely business logic.

As for the trigger, when the container is up, for example, tomcat or jboss, the specified xml file will be defined and the injected content will be automatically identified.

What is the principle of spring ioc aop? What should I do during the interview? Good interview skills

I will give you an authoritative answer, and you will not have to answer this question.
IOC (Reverse Control): controls the assignment of member variables from the code to the configuration file.
AOP: Aspect (Aspect) Oriented (for) Programming (Programming), for Aspect Programming.
That's enough. Let's look at Spring's transaction processing, basically.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.