顾名思义为某个类的对象提供代理服务,协助该对象解决核心方法以外的问题。
静态代理:委托类对象运行之前,代理类对象已经存在。且服务于某些特定类对象(同一个接口下)。
静态代理举例:
public interface Service {
void add();
void del();
void update();
void query();
}
/**
* 用户实际操作
*/
public class UserServiceImpl implements Service {
public void add() {
System.out.println("用户添加操作!");
}
public void del() {
System.out.println("用户删除操作!");
}
public void update() {
System.out.println("用户更新操作!");
}
public void query() {
System.out.println("用户查询操作!");
}
}
/**
* 记录用户操作的代理类:
*/
public class UserLogProxy implements Service {
private Service userService;
public UserLogProxy(Service userService){
this.userService=userService;
}
public void add() {
before("add");
userService.add();
after("add");
}
public void del() {
before("del");
userService.del();
after("del");
}
public void update() {
before("update");
userService.update();
after("update");
}
public void query() {
}
public void before(String method){
System.out.println("用户开始执行"+method+"方法!");
}
public void after(String method){
System.out.println("用户执行完"+method+"方法!");
}
}
/**
* 测试方法执行
*/
public static void main(String[] args) {
Service user=new UserLogProxy(new UserServiceImpl() );
user.add();
user.del();
}
优点:代码类不需要了解委托类的具体实现,客户端方法调用时,只需要知道代理类对象即可。
缺点:代码冗余,维护性差。代理类和委托类实现了相同接口,如果我接口中有上百个方法,则代理类需要手动对上百个方法的添加日志记录信息。
动态代理:
程序运行时通过反射动态产生代理类。
/**
*日志处理器
*/
public class LogProxyHandler implements InvocationHandler {
public Object targetObject;//目标对象
public Object newProxyInstance(Object targetObject){
this.targetObject=targetObject;
/**
* 生成代理类实例:
* 第一个参数:指定代理类的类加载器。需要将其指定为和目标对象同一个类加载器
* 第二个参数:代理类要实现的接口。使用目标对象的接口
* 第三个参数:执行方法时,需要执行哪个InvocationHandler的invoke方法
*/
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this);
}
/**
* 代理类执行的方法
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before(method.getName());
method.invoke(targetObject, args);
after(method.getName());
return null;
}
//扩展模块
private void before(String name){
System.out.println(name+"方法执行开始!");
}
//扩展模块
private void after(String name){
System.out.println(name+"方法执行结束!");
}
}
public class Test {
/**
* 测试方法执行
*/
public static void main(String[] args) {
Service service = (Service)(new LogProxyHandler()).newProxyInstance(new UserServiceImpl());
service.add();
createProxyClassFile();
}
/**
* 生成代理类文件
*/
public static void createProxyClassFile() {
@SuppressWarnings("restriction")
byte[] data = ProxyGenerator.generateProxyClass("$Proxy1",new Class[]{Service.class});
//字节数组通过流的形式保存项目文件
try {
FileOutputStream out=new FileOutputStream("$Proxy1.class");
out.write(data);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
反编译生成的代理文件:
import cn.rjx.tq.sproxy.Service;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy1
extends Proxy
implements Service
{
private static Method m1;
private static Method m5;
private static Method m2;
private static Method m3;
private static Method m6;
private static Method m0;
private static Method m4;
public $Proxy1(InvocationHandler paramInvocationHandler)
throws
{
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject)
throws
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void query()
throws
{
try
{
this.h.invoke(this, m5, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
throws
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void add()
throws
{
try
{
this.h.invoke(this, m3, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void del()
throws
{
try
{
this.h.invoke(this, m6, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void update()
throws
{
try
{
this.h.invoke(this, m4, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m5 = Class.forName("cn.rjx.tq.sproxy.Service").getMethod("query", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m3 = Class.forName("cn.rjx.tq.sproxy.Service").getMethod("add", new Class[0]);
m6 = Class.forName("cn.rjx.tq.sproxy.Service").getMethod("del", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m4 = Class.forName("cn.rjx.tq.sproxy.Service").getMethod("update", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}
可以看出jdk动态代理在运行时生成一个代理类文件。通过我们传入的InvocationHandler实例,由代理类实例调用invoke().
感觉动态代理是将(A*C+B*C)转换成(A+B)*C,A,B为用户核心代码,C为方法执行前后的相同操作,比如日志管理,权限管理等。这就是AOP的基本思想吧。