天天看点

java 动态代理与静态代理静态代理jdk动态代理cglib代理

        代理在生活中比较常见,比如常见的代理商,对工厂进行代理,工厂专注生产,代理商负责经销,用户购买商品从代理商手中购买。java中代理分为动态代理与静态代理,其中动态代理比较常见的有jdk动态代理和cglib动态代理。

静态代理

        静态代理实现简单,但不够灵活,比较麻烦,要实现与被代理对象一样的接口,创建很多代理类。接口增加方法后代理类与被代理对象都要加方法。以日志代理举例:

   1.创建订单接口     

/**
 * 订单接口
 * 
 * @author huaisf
 *
 */
public interface OrderService {

	/**
	 * 保存订单
	 */
	void saveOrder();

	/**
	 * 查询订单
	 */
	void selectOrder();

}
           

2.创建实现类

/**
 * 订单接口实现
 * 
 * @author huaisf
 *
 */
public class OrderServiceImpl implements OrderService {

	public void saveOrder() {
		System.out.println("保存成功");
	}

	public void selectOrder() {
		System.out.println("查询成功");

	}

}
           

3.创建代理类

/**
 * 日志代理
 * 
 * @author huaisf
 *
 */
public class LoggerProxy implements OrderService {

	private OrderServiceImpl orderServiceImpl;

	public LoggerProxy(OrderServiceImpl orderServiceImpl) {
		this.orderServiceImpl = orderServiceImpl;
	}

	/**
	 * 执行方法前后打印日志,由于接口单继承,现在想给用户服务打印日志要专门写一个用户的loggerProxy,
	 * 而且OrderService增加方法,代理类也要变动
	 */
	public void saveOrder() {
		System.out.println("执行前打印日志");
		orderServiceImpl.saveOrder();
		System.out.println("执行后打印日志");
	}

	public void selectOrder() {
		System.out.println("执行前打印日志");
		orderServiceImpl.saveOrder();
		System.out.println("执行后打印日志");
	}

}
           

4.编写测试类

public class Test {

	public static void main(String[] args) {
		OrderServiceImpl orderServiceImpl = new OrderServiceImpl();
		LoggerProxy loggerProxy = new LoggerProxy(orderServiceImpl);
		loggerProxy.saveOrder();
	}
}
           

jdk动态代理

        只针对接口代理,相比于静态代理来说不用写大量重复代码,不用实现接口。在进行代理时,其使用反射机制生成一个实现代理接口的匿名类,然后重写该方法,生成的速度快,但基于反射,后续调用慢。还以日志代理举例:

1.创建订单接口

/**
 * 订单接口
 * 
 * @author huaisf
 *
 */
public interface OrderService {

	/**
	 * 保存订单
	 */
	void saveOrder();

	/**
	 * 查询订单
	 */
	void selectOrder();

}
           

2.创建实现类

/**
 * 订单接口实现
 * 
 * @author huaisf
 *
 */
public class OrderServiceImpl implements OrderService {

	public void saveOrder() {
		System.out.println("保存成功");
	}

	public void selectOrder() {
		System.out.println("查询成功");

	}

}
           

3.编写动态代理接口

package com.shaofei.controller;

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

/**
 * 日志代理
 * 
 * @author huaisf
 *
 */
public class LoggerProxy {

	private Object oject;

	public LoggerProxy(Object oject) {
		this.oject = oject;
	}

	/**
	 * 生成代理对象,不用实现接口,代理方法只需写一次,新增被代理类可复用
	 * 
	 * @return
	 */
	public Object getProxyInstance() {
		return Proxy.newProxyInstance(oject.getClass().getClassLoader(), oject.getClass().getInterfaces(),
				new InvocationHandler() {
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("执行前打印日志");
						Object returnValue = method.invoke(oject, args);
						System.out.println("执行后打印日志");
						return returnValue;
					}
				});
	}
}
           

4.编写测试类

public class Test {

	public static void main(String[] args) {
		OrderService orderService = new OrderServiceImpl();
		OrderService proxy = (OrderService) new LoggerProxy(orderService).getProxyInstance();
		proxy.saveOrder();
	}
}
           

cglib代理

        cglib代理也叫子类代理,基于继承机制,通过asm字节码框架转换字节码重写父类方法达到增强作用,所以被代理类不能为final,其方法不能为final或static。其缺点为生成字节码较慢,但生成后调用快。

1.引入cglib依赖,目前最新版本为3.3.0。

<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib</artifactId>
			<version>3.3.0</version>
		</dependency>
           

2.创建被代理类

/**
 * 订单接口
 * 
 * @author huaisf
 *
 */
public class OrderServiceImpl {
	/**
	 * 保存订单
	 */
	public void saveOrder() {
		System.out.println("保存成功");
	}

	/**
	 * 查询订单
	 */
	public void selectOrder() {
		System.out.println("查询成功");

	}

}
           

3.创建cglib代理类

/**
 * 日志代理
 * 
 * @author huaisf
 *
 */
public class LoggerProxy implements MethodInterceptor {
	private Object oject;

	public LoggerProxy(Object oject) {
		this.oject = oject;
	}

	public Object getProxyInstance() {
		Enhancer enhancer = new Enhancer();
		// 设置enhancer对象的父类
		enhancer.setSuperclass(oject.getClass());
		// 设置enhancer的回调对象
		enhancer.setCallback((Callback) this);
		// 创建代理对象
		return enhancer.create();

	}

	public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
		System.out.println("执行前打印日志");
		Object object = methodProxy.invokeSuper(sub, objects);
		System.out.println("执行后打印日志");
		return object;

	}
}
           

4.编写测试类

public class Test {

	public static void main(String[] args) {
		OrderServiceImpl target = new OrderServiceImpl();
		OrderService proxy = (OrderService) new LoggerProxy(target).getProxyInstance();
		proxy.saveOrder();
	}
}