一、什么是代理
举例说明:当我想买一台电脑,国内太贵了。委托好友A在国外帮忙买。
这个情节中我要实现的动作和好友实现的动作一样,都是买电脑。好友帮我完成了这个动作,这就是代理。
类A和类B都实现一个interface接口C,C规定了A和B要完成的动作。借助B类实现A类完成接口中的动作。
1.使用代理的场景?
(1)功能增强:B完成接口中的动作之余还做了别的事情
(2)控制访问:B不让A访问到目标类,只有通过B这个媒介,A才能访问
二、静态代理
静态代理就是:自己写类实现代理。
思路:一个接口C,一个代理类B,一个被代理类A。两个类都实现接口C,在B实现接口中的方法时调用A对象方法。
接口C:
public interface Singer {
void singing();
int dance();
}
被代理类A
public class Cai implements Singer {
@Override
public void singing() {
System.out.println("cai 唱歌");
}
@Override
public int dance() {
System.out.println("tiaowu");
return 0;
}
}
代理类A
public class Caidaili implements Singer{
private Singer cai = new Cai();
@Override
public void singing() {
System.out.println("先收钱");
cai.singing();
}
@Override
public int dance() {
System.out.println("先收钱");
cai.dance();
return 0;
}
}
测试
public class Main {
public static void main(String[] args) {
Singer singer = new Caidaili();
singer.singing();
singer.dance();
}
}
静态代理的局限性:如果被代理类太多了,每个被代理类都要有一个代理。这样写的代理类就太多了。因此引入动态代理,动态决定被代理类。
三、动态代理
动态代理就是不需要自己写代理类了,通过反射或者继承实现。动态代理有两种模式:
(1)jdk动态代理
通过反射类实现代理
核心代码:
Proxy.newProxyInstance(被代理的类的类加载器,被代理类实现的接口,实现InvocationHandler的类对象)
返回:代理类对象
参数列表中:InvocationHandler接口(函数式接口)重写了invoke方法,重写代码中的核心:
被代理对象.方法()
method.invoke(接口对象,参数) //表示调用这个接口中的方法
实例:
接口
public interface Singer {
void dance();
int singing();
}
被代理类
public class Cai implements Singer {
@Override
public void dance() {
System.out.println("Cai 在跳舞");
}
@Override
public int singing() {
System.out.println("Cai 在唱歌");
return 0;
}
}
jdk动态代理实现
public class Test1 {
public static void main(String[] args) {
Cai cai =new Cai();
// Ruler ruler = new Ruler(cai);
//构建了 以原被代理类为基准的代理类的一个对象
// o 已经等同于 Student s = new Student(); 这个s了
Object o = Proxy.newProxyInstance(Cai.class.getClassLoader(), new Class[]{Singer.class}, (proxy, method, args1) -> {
System.out.println(proxy.getClass().toString());
System.out.println("先收钱");
Object returnVal = method.invoke(cai, args1);
System.out.println("asdfasdf");
return returnVal;
});
System.err.println(o.getClass().toString());
if(o instanceof Singer){
Singer singer = (Singer)o;
singer.dance();
singer.singing();
singer.toString();
}
}
}
(2)cglib动态代理
不写接口,通过继承关系重写方法实现代理
示例:
被代理类:
public class Singer {
public void dance(){
System.out.println("tiaowu");
}
public int singing(){
System.out.println("changge");
return 100;
}
}
代理类:
public class SingerSub extends Singer {
@Override
public void dance() {
System.out.println("shouqian");
super.dance();
}
@Override
public int singing() {
System.out.println("shouqian");
return super.singing();
}
}
测试:
public class Main {
public static void main(String[] args) {
Singer singer = new SingerSub();
singer.singing();
singer.dance();
}
}