基于Java的设计模式 - 代理模式

代理模式是一种使用代理对象来执行目标对象的方法并在代理对象中增强目标对象方法的一种设计模式。简单来讲就是在不修改目标对象的基础上,增强主业务逻辑的设计模式。

代理模式基本可分为三种

  • 静态代理
  • JDK动态代理
  • CGLIB动态代理

上述简单分就是静态和动态代理,静态代理即程序运行之前已创建了代理类,动态代理是程序运行时通过反射机制动态创建代理对象。

静态代理

DoService.java

//主业务接口
public interface DoService {
	void doSomething();
}

DoServiceImpl.java

public class DoServiceImpl implements DoService {

	@Override
	public void doSomething() {
		// TODO Auto-generated method stub
		System.out.println("业务操作");
	}

}

ServiceProxy.java

//代理类
public class ServiceProxy implements DoService {
	
	private DoService target;
	
	public ServiceProxy(){
		super();
		//创建目标对象
		target = new DoServiceImpl();
	}
	
	@Override
	public void doSomething() {
		// TODO Auto-generated method stub
		System.out.println("代理类--业务处理前操作");
		target.doSomething();
		System.out.println("代理类--业务处理后操作");
	}

}

TestStaticProxy.java

public class TestStaticProxy {
	public static void main(String[] args) {
		DoService service = new ServiceProxy();
		service.doSomething();
	}
}

JDK动态代理

DoService.java

//主业务接口
public interface DoService {
	void doSomething();
}

DoServiceImpl.java

public class DoServiceImpl implements DoService {

	@Override
	public void doSomething() {
		// TODO Auto-generated method stub
		System.out.println("业务操作");
	}

}

TestJdkProxy.java

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

public class TestJdkProxy {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		DoService target = new DoServiceImpl();
		// 使用JDK的Proxy动态代理,要求目标类必须实现接口
		// 因为其底层的执行原理,与静态代理相同
		DoService service = (DoService) Proxy.newProxyInstance(target.getClass().getClassLoader(), // 目标类的类加载器
			target.getClass().getInterfaces(), // 目标类所实现的所有接口
			new InvocationHandler() { // 匿名内部类

				// proxy:代理对象
				// method:目标方法
				// args 目标方法的参数列表
				@Override
				public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
					// TODO Auto-generated method stub
					System.out.println("代理类--业务处理前操作");
					// 调用目标方法
					Object result = method.invoke(target, args);
					System.out.println("代理类--业务处理后操作");
					return result;
				}
			});
		service.doSomething();
	}
}

使用jdk的proxy实现代理,要求目标类与代理类实现相同的接口,若目标类不存在接口,则无法使用该方式实现

CGLIB动态代理

DoService.java

//主业务
public class DoService {
	public void doSomething() {
		System.out.println("业务操作");
	}
}

MyCglibFactory.java

import java.lang.reflect.Method;

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

public class MyCglibFactory implements MethodInterceptor {

	private DoService target;
	
	public MyCglibFactory() {
		super();
		// TODO Auto-generated constructor stub
		target = new DoService();
	}
	
	public DoService MyCglibCreator(){
		//创建增强器对象
		Enhancer enhancer = new Enhancer(); 
		//指定目标类,即父类
		enhancer.setSuperclass(DoService.class);
		//设置回调接口对象
		enhancer.setCallback(this);
		
		return (DoService) enhancer.create();
	}
	
	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("代理类--业务处理前操作");
		Object result = method.invoke(target, args);
		System.out.println("代理类--业务处理后操作");
		return result;
	}

}

TestCglibProxy.java

public class TestCglibProxy {
	public static void main(String[] args) {
		DoService service = new MyCglibFactory().MyCglibCreator();
		service.doSomething();
	}
}

对于无接口的类,要为其创建动态代理,就要使用CGLIB来实现,CGLIB代理的生成原理是生成目标类的子类,而子类是增强过,这个子类对象就是代理对象,所以使用CGLIB生成动态代理,要求目标必须能够被继承,即不能是final的类

你可能感兴趣的:(java,设计模式,代理模式)