Design Patterns proxy mode (Java example) and its application in Spring-AOP features

Proxy mode:

Acting as a kind of model is the use of bridges that need to be proxied agent, the agent is first class to the agent needs to be a proxy object, rather than go directly to the proxy object through a proxy class in other objects need to use this object when . This can be enhanced by proxy objects in the proxy class. Proxy mode is divided into static and dynamic proxy agent.

Static Agent:

Static means the proxy object agent who at compile time on the set, which is achieved by proxy class to implement the interface and then by a combination.

example:

The proxy class interfaces:

package com.ustc;

public interface Sub {
    public void doSomething();
}

The proxy class:

package com.ustc;

import java.sql.SQLOutput;

public class SubImp implements Sub {

    @Override
    public void doSomething() {
        System.out.println("i have done");
    }
}

Acting categories:

package com.ustc;

public  class SubProxy the implements Sub {
    // implemented needs to be enhanced by the combination of the proxy class 
    Private Sub Object = null ;

    public SubProxy (){
    }
    public SubProxy(Sub object){
        this.object=object;
    }
    @Override
    public  void doSomething () {
         // enhanced class of agents is here 
        System.out.println ( "The Object Enhance Technology" );
         // in this method of the object corresponding to the call proxy class 
        SubProxy subProxy = new new SubProxy ( new new SubImp ());
        subProxy.object.doSomething();
        // After the object is processed proxy 
        System.out.println ( "handle somethings" );
    }
}

You can see, the proxy object agent who has been determined at compile time, so will there is a drawback: each agent must have to be a proxy class to its proxy and the proxy class to implement the proxy class All interface methods, high redundancy codes. ==== "dynamic agents can make up for this shortcoming.

Dynamic Proxy

Proxy objects are not determined at compile time, run time through reflection to dynamically create a proxy object, which was determined at run time who were proxy objects Yes. This can improve the code reusability. (Do not have to create a proxy class for each object being proxied, the proxy class and method of administration greatly enhanced rate).

First introduced: an interface and a method for dynamic proxy class depends.

Interface InvocationHandler

The official description:

InvocationHandlerActing is an example of the invocation handler implement.

Each proxy instance has an associated invocation handler. The method calls for the proxy instance, a method invocation encoded and assigned to its caller handler invokemethod. 

In fact, it corresponds to the static proxy class is overwritten by proxy interface that part of the program. (But which method is invoked through reflection)

He is only a need to implement interfaces:

 

 

 

 

 

Meaning three parameters:

 invoke three parameters:
Object proxy: proxy object
Method method: proxy object performing the presently described method of the object (by reflection)
Object [] args: Actual process parameters
How to dynamically create a proxy object?
Proxy.newProxyInstance

 

His three parameters:

parameter:

loader - define the proxy class class loader     

interfaces - list of interfaces proxy class to implement   

 h - assignment method invocation handler calls 

Dynamic proxy instance:

package com.ustc;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public  class SubDynamicProxy {
     public   SubDynamicProxy createSubDynamicProxy (String [] args) {
         // still achieve the object by combining 
        Sub Sub = new new SubImp ();
         // dynamically generated proxy object 
        SubDynamicProxy proxy = (SubDynamicProxy) Proxy.newProxyInstance ( SubDynamicProxy. class .getClassLoader (), sub.getClass (). The getInterfaces (), new new of InvocationHandler () {
            @Override
            public Object Invoke (Object O, Method, Method, Object [] args) throws the Throwable {
                 // enhancement method before performing the target method 
                System.out.println ( "before target Method Enhance Technology" );
                 // call to the target method, and give the object the method returns the result 
                Object outcome = Method.invoke (Sub, args);
                 // enhancement method is performed after the target 
                System.out.println ( "enhance Technology after target method" );
                 return outcome;
            }
        });
        return proxy;
    }
}

When required for use can be obtained through its SubImp proxy class, and may be enhanced by enhancing SubImp method. Another benefit: the interface is seen to achieve different dynamic proxy class agent, so the agent class interface when the change is not a proxy class will not have to change it? Such coupling reduces a lot.

Dynamic proxies in Spring-AOP Application:

The AOP (Aspect Oriented Programming): AOP uses a lateral extraction mechanism replacing the traditional architecture of the longitudinal inheritance.

How to understand this sentence on top of it?

Imagine a scenario:

There is a base class, we need to be enhanced, traditional how we do? === "inheritance, is vertical, so called traditional vertical inheritance.

Now we have by lateral extraction, i.e., preparation of a reinforcing class (placed inside enhancement method), and so on to enhance the class-based enhanced in the same level, then the proxy class through a combination of these two methods to sort class, is not reached enhanced purpose, while avoiding inheritance, to reduce the degree of coupling effect?

Spring-AOP examples:

Required classes and interfaces to be proxied:

public interface UserService {
      public void addUser();
      public void updataUser();
      public void deleUsr();
}
// target: to be proxied class 
public  class UserServiceImp the implements UserService {
      @Override
      public void addUser() {
             // TODO Auto-generated method stub
             System.out.println("addUser");
      }
      @Override
      public void updataUser() {
             // TODO Auto-generated method stub
             System.out.println("updateUser");
             
      }
      @Override
      public void deleUsr() {
             // TODO Auto-generated method stub
             System.out.println("deleUser");
             
      }
}

Cut class :( prevent enhancement)

public class MyAspect implements org.aopalliance.intercept.MethodInterceptor  {
      @Override
      public Object invoke(MethodInvocation mi) throws Throwable {
             System.out.println ( "before" );
              // call the target method 
             Object the proceed = mi.proceed ();
             System.out.println("后");
             return proceed;
      }
}

Then write configuration files, Spring plant generated proxy class through the configuration file (used here a framework AspectJ AOP, the self-view)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
             http://www.springframework.org/schema/aop
             http://www.springframework.org/schema/aop/spring-aop.xsd">
      <! - the target class to the spring ->
    <bean id="userServiceId" class="com.ustc.AOP.auto.UserServiceImp"></bean>
      <! - to cut class to the spring ->
      <bean id="myAspectId" class="com.ustc.AOP.auto.MyAspect"></bean>
! <- aopconfig by connecting them PointCut: pointcut expression: used to match an entry point. Which method is the need to strengthen. -> <- advisor:! Special section, only a notice and an entry point pointcut - ref: This section is the entry point for advice-ref notification. Put them together into a section -> <! - * to determine the target class, AspectJ pointcut expression, introducing jar package -> <!-- com.springsource.org.aspectj.weaver.jar --> <- pointcut expressions:! Execution (* com.ustc.AOP.auto.UserServiceImp *. (..) -> <aop:config > <aop:pointcut expression="execution(* com.ustc.AOP.auto.UserServiceImp.*(..))" id="myPointCut"/> <aop:advisor advice-ref="myAspectId" pointcut-ref="myPointCut"/> </aop:config> </beans>

 

After re-acquiring UserService that is to get its proxy object. In fact, Spring formation mechanism is the dynamic proxy proxy objects.

The dynamic proxy mechanism is verified by the source used in the bottom of Spring AOP:

AOP proxy structure:

 

 

 When there is no connection, it uses only cglib bytecode implementation class, when there is a dynamic proxy interfaces.

AOP proxy interface

public interface AopProxy {

    /**
     * Create a new proxy object.
     * <p>Uses the AopProxy's default class loader (if necessary for proxy creation):
     * usually, the thread context class loader.
     * @return the new proxy object (never {@code null})
    Object getProxy();

    /**
     * Create a new proxy object.
     * <p>Uses the given class loader (if necessary for proxy creation).
     * {@code null} will simply be passed down and thus lead to the low-level
     * proxy facility's default, which is usually different from the default chosen
     * by the AopProxy implementation's {@link #getProxy()} method.
     * @param classLoader the class loader to create the proxy with
     * (or {@code null} for the low-level proxy facility's default)
    Object getProxy(@Nullable ClassLoader classLoader);

}

Take for example enhanced dynamic proxy to view its method of obtaining proxy class

The method of generating a dynamic proxy SpringAOP:

public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
        }
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

    /**
     * Finds any {@link #equals} or {@link #hashCode} method that may be defined
     * on the supplied set of interfaces.
     * @param proxiedInterfaces the interfaces to introspect
     */
    private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
        for (Class<?> proxiedInterface : proxiedInterfaces) {
            Method[] methods = proxiedInterface.getDeclaredMethods();
            for (Method method : methods) {
                if (AopUtils.isEqualsMethod(method)) {
                    this.equalsDefined = true;
                }
                if (AopUtils.isHashCodeMethod(method)) {
                    this.hashCodeDefined = true;
                }
                if (this.equalsDefined && this.hashCodeDefined) {
                    return;
                }
            }
        }
    }

See top code is not very familiar with? Especially this one:

return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

Proxy mode is dynamic proxy previously introduced.

Therefore, the method is implemented SpringAOP dynamic proxy mechanism when an interface proxy class underlying employed.

Spring-AOP can view the source to the Maven repository to download and view, accompanied by Maven repository corresponding to the address:

  https://repo1.maven.org/maven2/springframework/spring-aop/

 

 Limited, there is an error, please point out!

Guess you like

Origin www.cnblogs.com/tlxclmm/p/12005391.html