一、动态代理和静态代理
1.静态代理
//静态代理实现
//共同接口
public interface Action {
public void doSomething();
}
//对象
public class RealObject implements Action{
public void doSomething() {
System.out.println("do something");
}
}
//代理对象
public class Proxy implements Action {
private Action realObject;
public Proxy(Action realObject) {
this.realObject = realObject;
}
public void doSomething() {
System.out.println("proxy do");
realObject.doSomething();
}
}
//运行代码
Proxy proxy = new Proxy(new RealObject());
proxy.doSomething();
静态代理扩展会导致Proxy不断膨胀;
2. 动态代理
public class DynamicProxyHandler implements InvocationHandler {
private Object realObject;
public DynamicProxyHandler(Object realObject) {
this.realObject = realObject;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//代理扩展逻辑
System.out.println("proxy do");
return method.invoke(realObject, args);
}
}
//实现
public static void main(String[] args) {
RealObject realObject = new RealObject();
Action proxy = (Action) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Action.class}, new DynamicProxyHandler(realObject));
proxy.doSomething();
}
Proxy.newProxyInstance 传入的是一个ClassLoader, 一个代理接口,和我们定义的handler,返回的是一个Proxy的实例。
仔细体会这个过程,其实有点类似我们在静态代理中提到的方案一,生成了一个包含我们扩展功能,持有RealObject引用,实现Action接口的代理实例Proxy。只不过这个Proxy不是我们自己写的,而是java帮我们生成的,有没有一点动态的味道。
让我们再回顾一下代理三要素:真实对象:RealObject,代理接口:Action,代理实例:Proxy
上面的代码实含义也就是,输入 RealObject、Action,返回一个Proxy。妥妥的代理模式。
二、动态代理与反射的关系
根据上图代码可知:动态代理是动态的创建代理和动态的处理方法的,这也是反射的一个重要体现之处;
三、动态代理的几种实现方法
1. JDK 自带的proxy方式
2. cglib 方式创建
public class CglibTest implements MethodInterceptor {
/**
* 生成Cglib代理对象
* @param cla 真实对象的class对象
* @return Cglib代理对象
*/
public Object getProxy(Class cla){
//CGLIB的增强类对象
Enhancer enhancer=new Enhancer();
//设置增强类型,增强真实对象
enhancer.setSuperclass(cla);
//定义代理逻辑对象为当前对象,要求当前对象实现MethodInterceptor中的抽象方法。
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object object, Method method, Object[] arg2, MethodProxy methodProxy) throws Throwable {
System.out.println("调用真实对象前");
Object result= methodProxy.invokeSuper(object, arg2);
System.out.println("调用真实对象后");
return result;
}
}
public class StudentService {
void study(){
System.out.println("学生在教师中静悄悄地在学习...");
}
}
public class MainClass {
public static void main(String[] args) {
CglibTest cglibTest=new CglibTest();
//绑定关系,返回的是StudentService的代理对象
StudentService studentService=(StudentService)cglibTest.getProxy(StudentService.class);
//执行代理对象的intercept()方法,而不是StudentService中的study()方法。
//CGLIB的具体实现没看,猜测可能使用了多态,enhancer.create() 返回的真实对象的子类,增强的逻辑在子类中。
studentService.study();
}
}
无论是JDK还是CGLIB实现动态代理,最后返回的代理对象可能是真实对象的子类,在子类中实现了方法的增强(猜测)。
使用动态代理可以在代码执行的前后加入控制逻辑。拦截器和AOP就是通过这种方式实现的。
四、AOP
这里:https://www.cnblogs.com/Wolfmanlq/p/6036019.html
上一篇:Java学习(7) -- 反射
专栏:Java 基础学习