Java学习(8) -- 动态代理

一、动态代理和静态代理

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 基础学习

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值