转载地址:https://blog.csdn.net/cd18333612683/article/details/61419024
前言
都说面向切面编程是代理模式的延续,今天就来研究一下这两者之间的关系
代理模式:一个类代表另一个类的功能。
静态代理的DEMO
话不多说,先看个关于静态代理的例子:有一个shape的接口,rectangle和simpleproxy,都实现shape的接口,这个接口中有draw和erase两个方法,simpleproxy保存一个rectangle的引用,代替实体去实现“画”和“清除”的方法
接口:shape
package simpleproxy;
public interface Shape {
void draw();
void erase();
}
Rectangle
package simpleproxy;
public class Rectangle implements Shape{
@Override
public void draw(){
System.out.println("draw Rectangle");
}
@Override
public void erase(){
System.out.println("erase Rectangle");
}
}
SimpleProxy
package simpleproxy;
public class SimpleProxy implements Shape {
Shape shape;
void setShape(Shape shape){
this.shape=shape;
}
@Override
public void draw(){
System.out.println("create Rectangle");
shape.draw();
}
@Override
public void erase(){
shape.erase();
System.out.println("destroy Rectangle");
}
}
SimpleProxyDemo控制台
package simpleproxy;
public class SimpleProxyDemo {
private Shape shape;
public SimpleProxyDemo(Shape shape){
this.shape=shape;
}
public static void main(String[] args ){
Rectangle target=new Rectangle();
SimpleProxy proxy=new SimpleProxy();
proxy.setShape(target);
SimpleProxyDemo demo=new SimpleProxyDemo(proxy);
demo.shape.draw();
demo.shape.erase();
}
}
UML
但是我们仔细研究一下静态代理的代码,只有这个与之相对应的代理类可以代替rectangle类去做一些事情,没有办法让别的代理去做,只能“一对一”,所以说代码灵活性不够,但是我们如何解决这个问题呢??那就是动态代理,Spring AOP使用动态代理技术有两只机制:一个是JDK实现;另一种是cglib实现,下边讨论一下JDK的方式
动态代理(jdk)DEMO
接口Shape和类Rectangle
同上
Handler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//把代理的逻辑放在InvocationHandler实现类中,从而可以让任意接口代理相同的逻辑
//InvocationHandler:代理实例的调用处理程序实现的接口
public class Handler implements InvocationHandler{
Object target;
Handler(Object target){
this.target=target;
}
@Override
public Object invoke(Object proxy,Method method,Object[] args)throws Throwable
{
System.out.println("create Target");
//当代理对象调用真实对象的方法时,他会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
//通过反射执行某个类的某方法
Object o=method.invoke(target, args);
System.out.println("destroy Target");
return o;
}
}
客户端
package simpleproxy;
import java.lang.reflect.Proxy;
public class DynamicProxyDemo {
public static void main(String[] args){
//实际的类
Rectangle rectangle=new Rectangle();
Handler h=new Handler(rectangle);
//通过java API创建类newProxyInstance(动态加载代理类,代理类实现接口,使用handler)
//返回一个的顶接口的代理类实例(动态生成代理的核心)
Shape proxyShape=(Shape)Proxy.newProxyInstance
(Rectangle.class.getClassLoader(),
Rectangle.class.getInterfaces(), h);
proxyShape.draw();
proxyShape.erase();
}
}
接口Shape和Rectangle没有变化,不重复写了
JDK动态代理如何实现?
JDK动态代理主要这几java.lang.reflect包下的两个类:Proxy类和InvocationHandler接口
InvocationHandler:
每一个动态代理类都必须实现InvocationHandler这个接口,每一个代理类的实例都关联到一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会反射到这个接口下的invoke方法进行调用
Proxy:
这个类用来动态创建一个代理对象的类
总结
动态代理解决了静态代理一对一的问题,使用反射机制可以动态的决定由任意类型的代理类去代理实际的类实现接口,提高了系统的可扩展性和可维护性,下一篇将总结具体的动态代理在spring如何实现AOP编程~