1、代理模式:
代理意为“代为处理”,有些事情交给代理人去处理,而目标对象只聚焦核心的业务,这就更加符合面向对象,各司其职,专业的事情交给专业的人来做。生活中用到代理随处可见。比如明星要演出,一些事情如商谈合作,出场费用,演出项目,酒店安排,出现方式等都要经济人去协调洽谈。这个时候经济人其实就是明星的代理人。在java中把这种场景的应用抽象成一种代理模式。
2、实现原理:
就是原本直接找具体的对象就可以的事情,现在要先经过该对象的代理对象来处理。比如请明星商演,要先联系他的代理确定档期,出场费,衣食住行及规格等等。然后明星才去演出。换到程序中,就是对象执行具体的方法前后先做一下其他的程序处理。代理模式的用途其实就是对目标对象的增强。对目标对象的一些功能添加额外的功能。
3、实现方式
实现方式有三种:静态代理、jdk动态代理(一般称动态代理)、cglib动态代理(一般称为cglib代理)
3.1、静态代理:
程序设计的时候就已经又代理类了。
// 表演接口
public interface Perform {
void sing();
void dance();
}
// 明星类实现了表演接口
public class SuperStar implements Perform {
@Override
public void sing() {
System.out.println("明星开始唱歌 ... ");
}
@Override
public void dance() {
System.out.println("明星开始跳舞 ... ");
}
}
// 代理类也实现了表演接口
public class StaticProxy implements Perform {
// 内部并维护了表演接口的引用
private Perform star;
public StaticProxy(Perform star) {
this.star = star;
}
@Override
public void sing() {
System.out.println("已审查");
System.out.println("已收出场费");
star.sing();
System.out.println("接明星回下榻五星级酒店休息");
}
@Override
public void dance() {
System.out.println("已审查");
System.out.println("已收出场费");
star.dance();
System.out.println("接明星回下榻五星级酒店休息");
}
// 静态代理测试
public static void main(String[] args) {
StaticProxy staticProxy = new StaticProxy(new SuperStar());
staticProxy.sing();
staticProxy.dance();
}
}
3.2、jdk动态代理:
程序运行的时候才动态创建代理,采用jdk自带的proxy实现
public class TestDynamicProxy {
public static void main(String[] args) {
// 创建目标对象
SuperStar target = new SuperStar();
// 根据目标对象创建代理对象
Perform dynamicProxy = (Perform) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("表演前收出场费");
Object result = method.invoke(target, args);
System.out.println("表演完回酒店喝酒");
return result;
}
});
// 调用代理对象的方法
dynamicProxy.sing();
}
}
3.3、cglib动态代理:
程序运行的时候才动态创建代理,采用第三方cglib实现。
// 引入三方jar cglib
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
// 去除实现接口
public class SuperStar2{
public void sing() {
System.out.println("明星开始唱歌 ... ");
}
public void dance() {
System.out.println("明星开始跳舞 ... ");
}
}
public class TestCglibProxy {
public static void main(String[] args) {
// 1、创建增强对象Enhancer
Enhancer enhancer = new Enhancer();
// 2、设置要代理的目标类未代理类的父类
enhancer.setSuperclass(SuperStar2.class);
// 3、设置回调函数
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] agrs, MethodProxy methodProxy) throws Throwable {
System.out.println("收出场费");
return methodProxy.invokeSuper(o, agrs);
}
});
// 4、创建代理对象
SuperStar2 cglibProxy = (SuperStar2) enhancer.create();
// 5、执行代理对象方法
cglibProxy.sing();
}
总结和对比:
1、静态代理:要求代理类和目标类都要实现同一接口,并且代理类内部维护了目标类对象的引用。
2、jdk动态代理:只要求目标对象要实现接口,代理类不需要实现接口。
3、cglib动态代理:要引入cglib包,不需要目标类实现接口即可代理。