Java之——Spring AOP的两种代理

转载请注明出处:https://blog.csdn.net/l1028386804/article/details/80295523

Spring AOP主要有两种代理方式:

1.JDK动态代理  2.cglib代理
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
注:JDK动态代理要比cglib代理执行速度快,但性能不如cglib好。所以在选择用哪种代理还是要看具体情况,一般单例模式用cglib比较好,具体原因请自行百度。

一、JDK动态代理实现(原理是使用反射机制)

1、定义TestService接口

package io.mykit.proxy.jdk.service;

/**
 * JDK动态代理Service
 * @author liuyazhuang
 *
 */
public interface TestService {
	
	int add();
}

2、定义TestServiceImpl实现类

package io.mykit.proxy.jdk.service.impl;

import io.mykit.proxy.jdk.service.TestService;

public class TestServiceImpl implements TestService {

	@Override
	public int add() {
		System.out.println("开始执行add...");
		return 0;
	}

}

3、定义动态代理类JDKDynamicProxy

package io.mykit.proxy.jdk.handler;

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

/**
 * JDK的动态代理实现
 * @author liuyazhuang
 *
 */
public class JDKDynamicProxy implements InvocationHandler {

     //被代理的目标对象
    private Object proxyObj;  
   
    /**
     * Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
     * loader    :类加载器 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
     * interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
     * h         :一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
     */
      public Object newProxy(Object proxyObj){  
          this.proxyObj = proxyObj;
          //返回一个代理对象  
          return Proxy.newProxyInstance(proxyObj.getClass().getClassLoader(), proxyObj.getClass().getInterfaces(), this);  
      }  

     /**
      * 执行目标对象
      * Object  proxy:被代理的对象
      * Method  method:要调用的方法
      * Object  args[]:方法调用时所需要的参数
      */
       @Override
       public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {      
            before();
            Object object = method.invoke(this.proxyObj, args);  // 通过反射机制调用目标对象的方法
            after();      
            return object;  
        }
        public void before(){
             System.out.println("开始执行目标对象之前...");
        }
        public void after(){
            System.out.println("开始执行目标对象之后...");
	}
}

4、实现测试类ProxyTest

package io.mykit.proxy.jdk;

import io.mykit.proxy.jdk.handler.JDKDynamicProxy;
import io.mykit.proxy.jdk.service.TestService;
import io.mykit.proxy.jdk.service.impl.TestServiceImpl;

/**
 * 动态代理测试
 * 
 * @author liuyazhuang
 *
 */
public class ProxyTest {
	
	public static void main(String[] args) {
		// 我们要代理的真实对象
		TestService testService = new TestServiceImpl();
		testService.add();// 不是用代理
		System.out.println("===================================");
		JDKDynamicProxy JDKDynamicProxyTarget = new JDKDynamicProxy();
		TestService testServiceProxy = (TestService) JDKDynamicProxyTarget.newProxy(testService);
		// 执行代理类的方法
		testServiceProxy.add();
	}
}

5、测试结果如下

开始执行add...
===================================
开始执行目标对象之前...
开始执行add...
开始执行目标对象之后...

二、CGLIB代理

1、创建TestCGLIBServiceImpl类

package io.mykit.proxy.cglib.service.impl;
/**
 * 未实现接口的类
 * @author liuyazhuang
 *
 */
public class TestCGLIBServiceImpl {
    public int add() {
        System.out.println("开始执行add...");
        return 0;
    }
 }

2、创建代理类CGLIBProxy

package io.mykit.proxy.cglib.handler;

import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * 基于CGLIB实现
 * @author liuyazhuang
 *
 */
public class CGLIBProxy implements MethodInterceptor {

	private Object targetObject;// 被代理的目标对象

	/**
	 * 构造代理对象
	 * @param targetObject 传递的真实对象
	 * @return 代理对象
	 */
	public Object createProxyInstance(Object targetObject) {
		this.targetObject = targetObject;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(targetObject.getClass());// 设置代理目标
		enhancer.setCallback(this);// 设置回调
		return enhancer.create();
	}

	/**
	 * 在代理实例上处理方法调用并返回结果
	 * @param object : 代理类
	 * @param method  :被代理的方法
	 * @param args :该方法的参数数组
	 * @param methodProxy : 方法代理
	 */
	@Override
	public Object intercept(Object object, Method method, Object[] args, MethodProxy methodproxy) throws Throwable {
		Object result = null;
		try {
			System.out.println("前置处理开始 ...");
			result = methodproxy.invoke(targetObject, args);// 执行目标对象的方法
			System.out.println("后置处理开始  ...");
		} catch (Exception e) {
			System.out.println(" 异常处理 ...");
		} finally {
			System.out.println(" 调用结束 ...");
		}
		return result;
	}
}

3、创建测试类ProxyTest

package io.mykit.proxy.cglib;

import io.mykit.proxy.cglib.handler.CGLIBProxy;
import io.mykit.proxy.cglib.service.impl.TestCGLIBServiceImpl;

/**
 * 测试CGLIB代理
 * @author liuyazhuang
 *
 */
public class ProxyTest {
	
	 public static void main(String[] args) {
         //我们要代理的真实对象
         TestCGLIBServiceImpl testCGLIB = new TestCGLIBServiceImpl();
         testCGLIB.add();
         System.out.println("======================================");
         CGLIBProxy CGLIBproxy = new CGLIBProxy();
         TestCGLIBServiceImpl testCGLIBProxy = (TestCGLIBServiceImpl) CGLIBproxy.createProxyInstance(testCGLIB);
         testCGLIBProxy.add();
      }
}

4、测试结果

开始执行add...
======================================
前置处理开始 ...
开始执行add...
后置处理开始  ...
 调用结束 ...

5、pom.xml中添加的Jar包

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<skip_maven_deploy>false</skip_maven_deploy>
	<jdk.version>1.8</jdk.version>
	<spring.version>4.1.0.RELEASE</spring.version>
</properties>

<dependencies>
   
  <dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-expression</artifactId>
	    <version>${spring.version}</version>
	</dependency>	
	
		<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-messaging</artifactId>
	    <version>${spring.version}</version>
	</dependency>
	
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-jms</artifactId>
	    <version>${spring.version}</version>
	</dependency>
	
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-aop</artifactId>
		<version>${spring.version}</version>
	</dependency>
	
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-jdbc</artifactId>
		 <version>${spring.version}</version>
	</dependency>
	
	 <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>

	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-context-support</artifactId>
	    <version>${spring.version}</version>
	</dependency>
	
	<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    
    <dependency>
	    <groupId>org.aspectj</groupId>
	    <artifactId>aspectjtools</artifactId>
	    <version>1.9.1</version>
	</dependency>
	
	<dependency>
	    <groupId>javax.servlet</groupId>
	    <artifactId>javax.servlet-api</artifactId>
	    <version>3.0.1</version>
	</dependency>

	<dependency>  
	    <groupId>org.slf4j</groupId>  
	    <artifactId>slf4j-log4j12</artifactId>  
	    <version>1.7.2</version>  
	</dependency> 
	
	  <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.1.1</version>
    </dependency>
     <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib-nodep</artifactId>
            <version>2.1_3</version>
        </dependency>
	
</dependencies>

猜你喜欢

转载自blog.csdn.net/l1028386804/article/details/80295523
今日推荐