JDK代理和CGLIB代理


學而時習之,不亦說乎!

                             --《論語》

AOP是spring的一個重要組成部分,而AOP通過代理實現。這兒寫下JDK代理和CGLIB代理兩種動態代理,為接下來的Spring AOP做准備。

JDK代理:

1)項目整體結構如下:

 

2)創建maven項目,pom.xml如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.zby</groupId>
	<artifactId>aop</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<!-- https://mvnrepository.com/artifact/cglib/cglib -->
		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib</artifactId>
			<version>3.2.5</version>
		</dependency>
	</dependencies>
</project>

這個依賴主要是給CGLIB用的,JDK代理並不需要。

3)創建UserService接口:

package com.zby.service;

public interface UserService {

	void saveUser(String username, String password);
}

4)創建UserService接口實現類UserServiceImpl:

package com.zby.service.impl;

import com.zby.service.UserService;

public class UserServiceImpl implements UserService {

	public void saveUser(String username, String password) {
		System.out.println("save user[username=" + username + ",password=" + password + "]");
	}

}

5)創建CustomAspect切面類:

package com.zby.aspect;

public class CustomAspect {

	public void startTransaction() {
		System.out.println("I get datasource here and start transaction");
	}



	public void endTrasaction() {
		System.out.println("I get datasource here and end transaction");
	}
}

6)創建JDKProxy代理工廠:

package com.zby.factory;

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

import com.zby.aspect.CustomAspect;

public class JDKProxy {

	public static Object createProxy(final Object targetObj, final CustomAspect customAspect) {
		// 使用JDK的Proxy類為目標類創建代理對象
		return Proxy.newProxyInstance(
				// 目標類使用的類加載器
				targetObj.getClass().getClassLoader(),
				// 目標類實現的接口
				targetObj.getClass().getInterfaces(),
				// 執行處理器,代理我們的業務邏輯
				new InvocationHandler() {
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						// 執行切面方法
						customAspect.startTransaction();
						// 具體邏輯代碼執行,返回值為方法執行結果
						Object result = method.invoke(targetObj, args);
						// 執行切面方法
						customAspect.endTrasaction();
						// 返回方法執行結果
						return result;
					}
				});
	}
}

  

7)編寫測試代碼:

package com.zby.test;

import org.junit.Test;

import com.zby.aspect.CustomAspect;
import com.zby.factory.JDKProxy;
import com.zby.service.UserService;
import com.zby.service.impl.UserServiceImpl;

public class JDKProxyTest {
	@Test
	public void testJDKProxy() {
		System.out.println("before Proxy......");
		UserService userService = new UserServiceImpl();
		userService.saveUser("zby", "1234567890");
		System.out.println("After Proxy......");
		UserService proxyUserService = (UserService)JDKProxy.createProxy(userService, new CustomAspect());
		proxyUserService.saveUser("zby", "1234567890");
	}
}

8)控制台打印結果:

before Proxy......
save user[username=zby,password=1234567890]
After Proxy......
I get datasource here and start transaction
save user[username=zby,password=1234567890]
I get datasource here and end transaction

CGLIB代理:

1)使用JDK代理創建的UserService接口,UserServiceImpl實現類和CustomAspect切面類。

2)創建CGLIB的代理類CGLIBProxy:

package com.zby.factory;

import java.lang.reflect.Method;

import com.zby.aspect.CustomAspect;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CGLIBProxy {

	public static Object createProxy(final Object targetObj, final CustomAspect customAspect) {
		Enhancer enhancer = new Enhancer();
		// 設置需要代理的父類
		enhancer.setSuperclass(targetObj.getClass());
		// 設置回調
		enhancer.setCallback(new MethodInterceptor() {
			@Override
			public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
					throws Throwable {
				// 執行切面方法
				customAspect.startTransaction();
				// 具體邏輯代碼執行,返回值為方法執行結果
				Object result = methodProxy.invokeSuper(proxy, args);
				// 執行切面方法
				customAspect.endTrasaction();
				// 返回方法執行結果
				return result;
			}
		});
		// 3.4 創建代理
		return enhancer.create();
	}
}

3)編寫測試類:

package com.zby.test;

import org.junit.Test;

import com.zby.aspect.CustomAspect;
import com.zby.factory.CGLIBProxy;
import com.zby.service.UserService;
import com.zby.service.impl.UserServiceImpl;

public class CGLIBProxyTest {
	@Test
	public void testJDKProxy() {
		System.out.println("before Proxy......");
		UserService userService = new UserServiceImpl();
		userService.saveUser("zby", "1234567890");
		System.out.println("After Proxy......");
		UserService proxyUserService = (UserService) CGLIBProxy.createProxy(userService, new CustomAspect());
		proxyUserService.saveUser("zby", "1234567890");
	}
}

4)控制台打印結果:

before Proxy......
save user[username=zby,password=1234567890]
After Proxy......
I get datasource here and start transaction
save user[username=zby,password=1234567890]
I get datasource here and end transaction

 5)CGLIB代理和JDK代理最大的區別就是:CGLIB代理的對象不需要實現任何接口,它使用的字節碼子類代理方式,但是JDK代理的對象必須實現接口。這兒使用CGLIB代理的時候,可以將UserService刪除,使用UserServiceImpl接收代理結果,效果完全一樣。

6)JDK代理的實質是生成一個實現我們傳入的接口,並且繼承Proxy的類;Cglib代理實質是繼承我們傳入的類。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM