第二十次总结 代理模式

  1. 什么是代理模式?
  2. 什么是静态代理?
  3. 什么是动态代理?
  4. 什么是Cglib?

1.什么是代理模式?

代理模式的主要作用是为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

 

 

 


2.什么是静态代理?

静态代理就是写死了在代理对象中执行这个方法前后执行添加功能的形式,每次要在接口中添加一个新方法,则需要在目标对象中实现这个方法,并且在代理对象中实现相应的代理方法,幸而Java有独特的反射技术,可以实现动态代理。

IPerson

 

 

 Pserson

 

 

 PersonProxy

 

 TextMain


3.什么是动态代理?

动态代理:Jdk动态代理和Cglib动态代理,Spring和AspectJ的动态代理是基于前面两种来实现的。
Jdk的动态代理,是使用反射技术获得类的加载器并且创建实例,根据类执行的方法在执行方法的前后发送通知。在代理对象Proxy的新建代理实例方法中,必须要获得类的加载器、类所实现的接口、还有一个拦截方法的句柄。在句柄的invoke中如果不调用method.invoke则方法不会执行。在invoke前后添加通知,就是对原有类进行功能扩展了。创建好代理对象之后,proxy可以调用接口中定义的所有方法,因为它们实现了同一个接口,并且接口的方法实现类的加载器已经被反射框架获取到了。

简而言之:静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。

1、创建Person类
创建 一个方法 int[] arrs(int[] oldArray)

创建Person代理类 在代理类中完成arrs方法的升序排序。

Iperson

 

 

Person

 

 MyInvocation

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocation implements InvocationHandler {
    private Class<Person> clazz;
    private  Person p;
    public MyInvocation(Class<Person> clazz) throws Exception {
        this.clazz=clazz;
        p=clazz.getDeclaredConstructor(null).newInstance(null);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if ("arrs".equals(method.getName())) {
            int[] msg = (int[]) args[0];
            for (int i = 0; i < msg.length - 1; i++) {
                for (int j = 0; j < msg.length - 1 - i; j++) {
                    if (msg[j] > msg[j + 1]) {
                        int temp = msg[j];
                        msg[j] = msg[j + 1];
                        msg[j + 1] = temp;
                    }
                }
            }
        }
        return method.invoke(p,args);
    }
}

 

ProxyFactory

import java.lang.reflect.Proxy;

public class ProxyFactory {
    public static  Object getProxyInstanc(Class targetClazz) throws Exception {
       Object targetProxy =Proxy.newProxyInstance(targetClazz.getClassLoader(),
               targetClazz.getInterfaces(),
               new MyInvocation(targetClazz));
       return targetProxy;
    }
}

 

Test

public class Test {
    public static void main(String[] args) throws Exception {
        Iperson iperson = (Iperson) ProxyFactory.getProxyInstanc(Person.class);
        int [] oldArray = {5,3,2,1,6,9,8};
        int [] result = iperson.arrs(oldArray);
        for (int i:result){
            System.out.print(i);
        }
    }
}

 

 


 

4.什么是Cglib?

 CGLib (Code Generation Library) 是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。Hibernate用它来实现PO字节码的动态生成。CGLib 比 Java 的 java.lang.reflect.Proxy 类更强的在于它不仅可以接管接口类的方法,还可以接管普通类的方法。
CGLib 的底层是Java字节码操作框架 —— ASM。

CGLIB和Java动态代理的区别:
1、Java动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为Proxy,Java类继承机制不允许多重继承);CGLIB能够代理普通类;
2、Java动态代理使用Java原生的反射API进行操作,在生成类上比较高效;CGLIB使用ASM框架直接对字节码进行操作,在类的执行过程中比较高效

 cglib核心代码:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
public class CGLIBProxyFactory {
//    获取代理对象
    public static Object getInstatnce(Class targetClass){
//        创建一个增强器对象
        Enhancer enhancer = new Enhancer();
//        设置代理的目标类
        enhancer.setSuperclass(targetClass);
//        设置一个拦截器
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                return null;
            }
        });
//        创建一个目标类的代理对象
        Object proxyObject = enhancer.create();
        return proxyObject;
    }

}

 

posted @ 2020-12-30 11:46  Zc小白  阅读(76)  评论(0)    收藏  举报