// 静态代理:
特点:实现起来简单,容易理解
缺点:当目标类很多的时候,代理类也会相应的增加很多
当接口改变了之后,所有的实现类,代理类都会受到影响
!!! 有一个大前提,必须要有接口才可以
例如:同事写好的代码,功能不够完善,需要在sout执行后增加部分代码,
tongshi.class-->Tongshi tongshi=new tongshi()-->sout("米饭")
在不改变原来代码的基础上,我们可以使用代理的方式,在sout执行之后,增加自己的代码
代理类需要自己实现,而且是确定的,
例子:
定义接口'人'
public interface people{
void sleep();
}
实现类'张三'
public class zhangsan implements people(){
@Override
public void sleep(){
sout("睡觉...")
}
}
现在有一个需求,张三需要在睡觉前把衣服洗了,并且睡醒之后下楼买菜
在不改变同事的类'zhangsan.class'的情况下
我们可以自己定义一个新的代理类'张三的管家'
public class steward implements people(){
private Zhangsan zhangsan= new zhangsan();
sout("洗衣服...");// 这里前置增强
zhangsan.sleep();
sout("下楼买菜...")// 这里后置增强
}
静态代理代理类会很多,维护起来很繁琐,但是比较简单
===============================================================
// 动态代理
在静态代理目标类很多的时候,我们可以使用动态代理,避免静态代理的缺点,代理类可以很少,接口方法修改也不会影响代理类
!!! '说白了就是使用java反射包实现创建代理类的方式,并且动态的指定要增强的目标类'
!!! '说白了就是使用java反射包实现创建代理类的方式,并且动态的指定要增强的目标类
我们使用动态代理实现这个张三的需求时,不需要创建新的代理类
三个重要的方法
1、 InvocationHanlder : 实现这个接口,重写invoke()方法 // 创建类实现InvocationHandler接口
2、 method.invoke(目标对象,方法参数)// 用来执行某个目标类的方法(invoke方法中的)
3、 Proxy.newProxyInstance(目标对象.getclass.getclassloader,目标对象.getclass.getInterface,InvocationHandler的实现类)// 用来获取jdk创建的目标类的代理对象
例子:
// 定义管家类实现InvocationHanlder接口
public class 管家 implements InvocationHandler(){
private Object target;// 用来代表目标类
public 管家(Object target){// 有参构造
this.target=target;
}
// 重写invoke方法
@Override
public Object invoke(Object proxy,Method method,Object[]args)throws Throwable{
sout("洗衣服...");// 前置增强
Object invoke = method.invoke(taget,args);
sout("下楼买菜");// 后置增强
return invoke;
}
}
测试一下:
class a{
psvm{
Zhangsan zhangsan = new zhangsan();
管家 管家 = new 管家(zahngsan);
People 代理对象 = (people)Proxy.newProxyInstance(zhangsan.getClass().getClassLoader(),zhangsan.getClass.getInterface(),管家);
代理对象.sleep();
}
}
输出结果:
洗衣服...
睡觉...
下楼买菜...