代理模式--静态代理--动态代理
在谈aop实现原理前,我们先说一下设计模式中的代理模式
1. 代理: 由代理类代理目标类执行目标类的方法。与装饰器模式的区别是 代理模式主要是控制对目标象的访问也可以增强对象的方法。但装饰器模式主要是对被装饰对象的扩展。
优点:
- 在执行目标对象创建及目标方法前后过程中 增加扩展代码 增加扩展性(aop切面)
- 决定对象的创建与方法的执行。智能化
2. 静态代理
提前创建代理对象
- 抽象接口(定义公共方法) 2 目标对象 3 代理对象
- 目标对象和代理对象都实现抽象接口。
代理对象掌握目标对象的引用
// 抽象接口
public interface Subject {String getName();
}
// 目标对象类
public class RealSubject implements Subject {String name;
public RealSubject(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
// 代理对象
public class ProxySubject implements Subject {RealSubject realSubject;
String name;
public ProxySubject(String name) {
this.name = name;
}
public String getName() {
String result = null;
System.out.println("目标方法执行前扩展");
try {
// 对象不存在创建对象。控制对象的访问
if (realSubject == null) {
realSubject = new RealSubject(this.name);
}
result = realSubject.getName();
System.out.println("目标方法执行返回结果后执行扩展" + result);
} catch (Exception e) {
System.out.println("目标方法执行异常扩展");
}
System.out.println("目标方法执行后扩展");
return result;
}
}
// 执行public static void main(String[] a) {
Subject subject = new ProxySubject("刘志强");
System.out.println(subject.getName());
}
缺点:每个类都要创建代理类 工作量大。
3. 动态代理
运行时由jdk通过反射机制创建代理对象(jdk代理)
编写动态代理处理类
public class DynamicProxyHandler implements InvocationHandler {
private Object object;
public DynamicProxyHandler(final Object object) {
this.object = object;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
System.out.println("目标方法执行前扩展");
try {
result = method.invoke(object, args);
System.out.println("目标方法执行返回结果后执行扩展" + result);
} catch (Exception e) {
System.out.println("目标方法执行异常扩展");
}
System.out.println("目标方法执行后扩展");
return result;
}
}
运行
public static void main(String[] a) {
Subject subject = new RealSubject("刘志强");
subject = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(), new
Class[]{ Subject.class}, new DynamicProxyHandler(subject));
System.out.println(subject.getName());
}
优点: 不需要给每个目标类创建代理类
然后我们在看看newProxyInstance 是如何创建对象的
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/* * 查找或生成指定的代理类。 */
Class<?> cl = getProxyClass0(loader, intfs);
/* * 使用指定的调用处理程序调用其构造函数。 */
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
// 获取构造方法
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
// 创建实例
return cons.newInstance(new Object[]{ h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
下面再说下JDKProxy和CGLIBProxy
CGLIB代理的由来及介绍
来自百度介绍
JDK的动态代理用起来非常简单,但它有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的继承的类,该怎么办?
CGLIB是一个强大的高性能的代码生成包。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。
CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。
还没有评论,来说两句吧...