间接对目标对象进行访问
可以详细控制某个对象的方法,对目标对象的实现功能上,增加额外的功能补充,扩展目标对象功能
1、安全代理:屏蔽对真实角色的直接访问
2、远程代理:通过代理类处理远程方法的调用
3、延时加载:先加载轻量级,真正需要再加载真实对象
1、静态代理
2、动态代理
3、Cglib代理
package com.hezeu.proxy.staticProxy;
/**
* @Classname Star
* @Description 抽象角色
* @Date 2020/2/22 下午 06:41
* @Created by 朱进博 1724282894@qq.com
*/
public interface Star {
void confer();
void signContract();
void bookTicket();
void sing();
void collectMoney();
}
真实角色:
package com.hezeu.proxy.staticProxy;
/**
* @Classname RealStar
* @Description TODO
* @Date 2020/2/22 下午 06:46
* @Created by 朱进博 1724282894@qq.com
*/
public class RealStar implements Star {
@Override
public void confer() {
System.out.println("RealStar.confer");
}
@Override
public void signContract() {
System.out.println("RealStar.signContract");
}
@Override
public void bookTicket() {
System.out.println("RealStar.bookTicket");
}
@Override
public void sing() {
System.out.println("RealSta(周杰伦本人).sing");
}
@Override
public void collectMoney() {
System.out.println("RealStar.collectMoney");
}
}
代理角色:
package com.hezeu.proxy.staticProxy;
/**
* @Classname ProxyStar
* @Description TODO
* @Date 2020/2/22 下午 06:48
* @Created by 朱进博 1724282894@qq.com
*/
public class ProxyStar implements Star{
private Star star;
public ProxyStar(Star star) {
this.star = star;
}
@Override
public void confer() {
System.out.println("ProxyStar.confer");
}
@Override
public void signContract() {
System.out.println("ProxyStar.signContract");
}
@Override
public void bookTicket() {
System.out.println("ProxyStar.bookTicket");
}
@Override
public void sing() {
star.sing();
}
@Override
public void collectMoney() {
System.out.println("ProxyStar.collectMoney");
}
}
测试:
package com.hezeu.proxy.staticProxy;
/**
* @Classname Client
* @Description 测试
* @Date 2020/2/22 下午 07:58
* @Created by 朱进博 1724282894@qq.com
*/
public class Client {
public static void main(String[] args) {
Star real = new RealStar();
Star proxy = new ProxyStar(real);
proxy.confer();
proxy.signContract();
proxy.bookTicket();
proxy.sing();
proxy.collectMoney();
}
}
测试结果如下:
静态代理的优缺点:优点:可以做到不修改目标对象功能的前提下对功能进行扩展或修改,符合开闭原则
缺点:因为代理对象需要与目标对象实现相同的接口,代理类爱多,同时一旦抽象角色增加方法,真实角色和代理角色都要维护,工作量大,不宜管理
使用JDK自带的动态代理
java.lang.reflect.Proxy 动态生成代理类和对象
java.lang.reflect.InvocationHandler(处理器接口)
可以通过invoke方法实现对真实角色的代理访问
每次通过proxy生成的代理类对象都要指定对应的处理器对象
package com.hezeu.proxy.dynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @Classname StarHandler
* @Description TODO
* @Date 2020/2/22 下午 08:16
* @Created by 朱进博 1724282894@qq.com
*/
public class StarHandler implements InvocationHandler {
Star realStar;
public StarHandler(Star realStar) {
this.realStar = realStar;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object obj = null;
System.out.println("真正的方法执行前!");
System.out.println("面谈,签合同,预付款,订机票");
if(method.getName().equals("sing")){
obj = method.invoke(realStar, args);
}
System.out.println("真正的方法执行后!");
System.out.println("收尾款");
return obj;
}
动态代理相较于静态代理的优缺点:
对于静态代理而言,动态代理建好了开发的任务,减少了对业务接口的依赖,降低了耦合度
三、Cglib代理:
第三方代理技术,可以对目标对象接口实现代理,也可以进行继承代理,底层是动态的在内存中生成了目标对象的子类的字节码,并生成了相应的对象。
CGlib实现动态代理能满足没有接口的目标对象的代理对象实现。JDK动态代理与CGlib动态代理是实现Spring AOP的基础
package com.hezeu.proxy.CGlib;
/**
* @Classname RealStar
* @Description TODO
* @Date 2020/2/22 下午 06:46
* @Created by 朱进博 1724282894@qq.com
*/
public class RealStar {
public void confer() {
System.out.println("RealStar.confer");
}
public void signContract() {
System.out.println("RealStar.signContract");
}
public void bookTicket() {
System.out.println("RealStar.bookTicket");
}
public void collectMoney() {
System.out.println("RealStar.collectMoney");
}
public void sing() {
System.out.println("RealStar(CGlib周杰伦).sing");
}
}
cglib代理类,需要实现MethodInterceptor
package com.hezeu.proxy.CGlib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @Classname ProxyStar
* @Description TODO
* @Date 2020/2/22 下午 10:09
* @Created by 朱进博 1724282894@qq.com
*/
public class ProxyStar implements MethodInterceptor {
private Object target;
public Object getInstance(Object target){
this.target=target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("事物开始");
Object result = methodProxy.invokeSuper(o,objects);
System.out.println("事物结束");
return result;
}
}
测试类:
package com.hezeu.proxy.CGlib;
/**
* @Classname Client
* @Description TODO
* @Date 2020/2/22 下午 08:20
* @Created by 朱进博 1724282894@qq.com
*/
public class Client {
public static void main(String[] args) {
ProxyStar proxy = new ProxyStar();
RealStar realStar = (RealStar) proxy.getInstance(new RealStar());
realStar.sing();
}
}
动态代理和CGlib代理总结
使用JDK动态代理需要实现一个或多个接口,若想代理没有实现接口的类,需要使用Cglib
使用Cglib 需要导入
cglib-xxx.jar
asm-xxx.jar
在Spring的AOP编程中
如果加入容器的目标对象有实现接口用JDK代理
如果目标对象没有实现接口,用Cglib代理
感谢阅读,水平有限,如有错漏,还请不吝赐教