java代理

分类和代码示例:

目录

静态代理

动态代理

JDK代理

Cglib代理

JDK代理和Cglib代理的区别


静态代理

可能会引起类爆炸

类爆炸:类的数量太多引发的问题

//衣服接口
public interface ByClothes {
    void clothes(String size);
}

//服装工厂类,具有制作衣服的功能
public class ClothesFactory implements ByClothes{

    @Override
    public void clothes(String size) {
        System.out.println("为您制作了一件大小为"+size+"的衣服");
    }

}

//服装工厂代理类
 public class ClothesProxy implements ByClothes{
    public ClothesFactory factory=new ClothesFactory();
    @Override
    public void clothes(String size) {
        frontService();
        factory.clothes(size);
        endService();
    }
    public void frontService() {
        System.out.println("售前服务");
    }
    public void endService() {
        System.out.println("售后服务");
    }
}

//测试类
 public class Test {

    public static void main(String[] args) {
        ClothesProxy proxy=new ClothesProxy();
        proxy.clothes("x1");
    }
}

执行结果:
售前服务
为您制作了一件大小为x1的衣服
售后服务

动态代理

JDK代理

基于接口,通过反射

//包包接口
public interface ByBag {
    void bag(String color);
}

//包包工厂类,具有制作包包的功能
public class BagFactory implements ByBag{
    @Override
    public void bag(String color) {
        System.out.println("为您制作了一款颜色为"+color+"的包");
    }
}

//包包工厂代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;



public class BagProxy implements InvocationHandler{
    private Object fattory;
    public Object getFattory() {
        return fattory;
    }
    

public void setFattory(Object fattory) {
        this.fattory = fattory;
    }

    @Override
    public Object invoke(Object proxy,Method method,Object[] args)throws Throwable {
        frontService();
        method.invoke(fattory, args);
        endService();
        return null;
    }
    
    public void frontService() {
        System.out.println("售前服务");
    }
    public void endService() {
        System.out.println("售后服务");
    }
    
    public Object getProxyInstence() {
        return Proxy.newProxyInstance(fattory.getClass().getClassLoader(), fattory.getClass().getInterfaces(), this);
    }
}

//测试类
public class Test {

    public static void main(String[] args) {
        BagFactory factory=new BagFactory();
        BagProxy proxy=new BagProxy();
        proxy.setFattory(factory);
        ByBag run=(ByBag)proxy.getProxyInstence();
        run.bag("蓝色");
    }
}

执行结果:
售前服务
为您制作了一款颜色为蓝色的包
售后服务

上面代理类中各个步骤的方法写得比较分散,也可以像下面这样集合到一个方法里面,自行取舍:

public class TargetProxy {
    public static   Object getTarget(T t) {
        //新构建了一个新的代理类的对象
        return Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // proxy就是目标对象t,method就是调用目标对象中方法,args就是调用目标对象中方法的参数。
                        //比如说:代理对象.method1(),这时proxy就是目标类,method1就是method,args就是method1方法参数。
                        System.out.println("执行方法前...");
                        Object invoke = method.invoke(t, args);
                        System.out.println("执行方法后...");
                        return invoke;
            }
        });
    }
}

Cglib代理

无需接口,通过继承

  • Cglib代理先通过Enhancer en = new Enhancer()创建增强对象en,再利用en.setSuperclass(target.getClass())设置代理对象target成为增强对象en的父类,让en和target具有继承关系
  • 两种等效的代理方法:
    • Object invoke = methodProxy.invokeSuper(object, args); 通过invokeSuper()方法,参数为子类对象object
    • Object invoke = method.invoke(t, args); 直接通过invoke方法,参数为父类对象t
//目标类
public class Target {
    public void method1() {
        System.out.println("method1 running ...");
    }
    public void method2() {
        System.out.println("method2 running ...");
    }
    public int method3(Integer i) {
        System.out.println("method3 running ...");
        return i;
    }
}
//代理类
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 TargetProxy {
    public static  Object getProxy(T t) {
        Enhancer en = new Enhancer(); //帮我们生成代理对象
        en.setSuperclass(t.getClass());//设置要代理的目标类(设置代理对象的父类)
        en.setCallback(new MethodInterceptor() {//代理要做什么
            @Override
            public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("执行方法前。。。");
                //调用原有方法  
                Object invoke = methodProxy.invokeSuper(object, args);
                // Object invoke = method.invoke(t, args);// 作用等同与上面。
                System.out.println("执行方法后。。。");
                return invoke;
            }
        });
        return en.create();
    }
}
//测试类
public class TargetUser {
    public static void main(String[] args) {
        Target target = (Target) TargetProxy.getProxy(new Target());
        target.method1();
    }
}

执行结果:
执行方法前。。。
method1 running ...
执行方法后。。。

JDK代理和Cglib代理的区别

  • jdk代理只能对实现了接口的类进行代理,而cglib代理可以对普通类进行代理;
  • jdk代理是通过反射的方式来实现动态代理,而cglib则是通过为目标类生成一个子类的方式来实现动态代理;
  • 由于cglib代理是为目标类生成了一个子类,并对父类方法进行增强,所以目标类不能用final修饰;

你可能感兴趣的:(java基础,java)