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代理实质是继承我们传入的类。

posted @ 2017-06-05 16:47  java拌饭  阅读(2547)  评论(0编辑  收藏  举报