《代理模式》

代理模式

    • 1.静态代理
    • 2.动态代理
    • 3.Cglib代理

1.静态代理

  • 静态代理的特点:
    目标类和代理类都实现了同一接口
    ②比较容易实现
    ③在不修改目标类核心功能的前提下,很容易就可以对目标l类进行功能的增强
    ④缺点:因为目标类和代理类实现了同一接口,此时接口一旦发生改变,两个类都必须同时实现新增的功能(动态代理可以解决这一缺点)
/**
 *共同的接口
 */
public interface SingPerform {

    //举办演唱会
    void sing();
}

/**
 * 目标类:做主要工作的类.
 */
public class Singer implements SingPerform {

    @Override
    public void sing() {
        System.out.println("大歌星开始唱歌啦....");
    }
}

/**
 * 代理类:执行辅助性的一些功能
 * 利用有参构造函数引入目标类
 * 对目标类的核心功能进行增强
 */
public class Broker implements SingPerform {

    private Singer singer;

    public Broker(Singer singer) {
        this.singer = singer;
    }

    @Override
    public void sing() {
        System.out.println("经纪人开始准备演唱会啦...");

        singer.sing();

        System.out.println("经纪人为演唱会善后...");
    }
}
/**
 *静态代理测试
 */
public class StaticProxyTest {

    public static void main(String[] args){
        Singer singer=new Singer();
        Broker broker=new Broker(singer);
        broker.sing();
        /*  结果:"经纪人开始准备演唱会啦..."
                 "大歌星开始唱歌啦...."
                 "经纪人为演唱会善后..." */
    }
}

2.动态代理

  • 动态代理的特点
    目标类实现接口,代理类不实现接口
    ②以后目标类根据需要扩展接口的功能,而不会影响到代理类
    利用反射实现,性能不高
/**
*目标类的接口
*/
public interface SingPerform {

    //举办演唱会
    void sing();
}
/**
 * 目标类:做主要工作的类.
 */
public class Singer implements SingPerform {

    @Override
    public void sing() {
        System.out.println("大歌星开始唱歌啦....");
    }

}
/**
 * 代理类:用来执行一些辅助性工作的类.
 */
public class Broker {

    public void prepareSing() {
        System.out.println("经纪人开始准备演唱会...");
    }

    public void afterSing() {
        System.out.println("经纪人为演唱会善后...");
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 代理工厂:在这里具体实现动态代理
 */
public class ProxyFactory {

    private Object target;//Singer
    private Broker broker;

    public ProxyFactory(Object target, Broker broker) {
        this.target = target;
        this.broker = broker;
    }

    //创建出以目标类为模板的代理对象的方法
    public Object newInstance() {
        Class<?> clazz = this.target.getClass();
        //得到目标类的类加载器
        //ClassLoader classLoader = clazz.getClassLoader();

        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {

            //创建出一个目标类的代理对象: 以目标类为模板,克隆出目标类的一个副本,然后以此为模板创建出一个对象,该对象就是目标类的代理对象
            //proxy:就是克隆出的代理对象(歌星的分身)
            //method:歌星的分身要执行的方法--->sing(),play(),xidu()
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                broker.prepareSing();

                //target.sing();
                //target.method(args)
                Object obj = method.invoke(target, args);

                broker.afterSing();

                return obj;
            }
        });
    }

}
/**
 *动态代理的测试
 */
public class DynamicProxyTest {

    public static void main(String[] args) {
        Singer target = new Singer();
        Broker broker = new Broker();
        ProxyFactory factory = new ProxyFactory(target, broker);
        //注意:此处必须转换为目标类的父类:接口
        SingPerform perform = (SingPerform) factory.newInstance();
        perform.sing();
    }

}

3.Cglib代理

  • Cglib代理的特点
    代理类和目标类都无需实现接口
    但是以目标类为父类,创建出一个功能增强的子类
    Spring中AOP的实现原理就是用的代理模式–>动态代理+Cglib代理
    (如果目标类实现了接口,Spring底层实现AOP就调用动态代理,否则就调用Cglib代理)

    Cglib是一个强大的高性能的代码生成包,它可以在运行期间扩展java类与实现java接口,它广泛的被许多Aop框架所使用
    Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类
/**
 * 
 * 1.目标类UserDaoImpl:执行核心功能,CRUD.
 *
 * 在进行增删改的时候,自动为这3个方法添加事务功能,查询方法除外
 * 事务的具体实现逻辑:
 * ① 开启事务;
 * ② 执行核心功能代码;
 * ③ 提交事务.
 *
 * 
 */
public class UserDaoImpl {

    public void insert(){
        //System.out.println("开启事务...");
        System.out.println("添加用户");
        //System.out.println("提交事务...");
    }

    public void delete(){
        //System.out.println("开启事务...");
        System.out.println("删除用户");
        //System.out.println("提交事务...");
    }

    public void update(){
        System.out.println("修改用户");
    }

    public void find(){
        System.out.println("查询用户");
    }
}
/**
 * 2.代理类:执行辅助性的额外功能.
 */
public class Transaction {

    public void beginTransaction(){
        System.out.println("开启事务了...");
    }

    public void commit(){
        System.out.println("提交事务了...");
    }
}

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

import java.lang.reflect.Method;

/**
 *3.Cglib代理类
 *
 */
public class DaoInterceptor implements MethodInterceptor {

    private Object target;//目标类--->只能进行crud;
    private Transaction transaction;//代理类--->只有事务的代码

    public DaoInterceptor(Object target, Transaction transaction) {
        this.target = target;
        this.transaction = transaction;
    }

    //创建出一个Cglib代理对象:执行带有事务功能的crud任务.也就是该对象把事务与crud合二为一了!
    //proxy=target+transaction
    public Object createProxyInstance() {
        //Enhancer增强者:给目标类增强,添加事务功能
        Enhancer enhancer = new Enhancer();
        //为什么要获取目标类的字节码?
        Class<?> clazz = this.target.getClass();
        enhancer.setClassLoader(clazz.getClassLoader());
        enhancer.setInterfaces(clazz.getInterfaces());
        //设置增强的回调函数
        enhancer.setCallback(this);
        //指定目标类,作为父类,以此为模板,创建出一个"儿子"出来
        enhancer.setSuperclass(clazz);

        //创建出一个增强目标类
        return enhancer.create();
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

        String methodName = method.getName();
        System.out.println("methodName=" + methodName);

        if ("find".equals(methodName)) {
            //直接执行find方法,不做额外操作
            method.invoke(target, args);
        } else {
            //对 增删改 进行了 增强!
            transaction.beginTransaction();

            method.invoke(target, args);

            transaction.commit();
        }

        return null;
    }

}


/**
 *Cglib代理测试类
 */
public class CglibTest {

    public static void main(String[] args) {
        UserDaoImpl target = new UserDaoImpl();
        Transaction transaction = new Transaction();
        DaoInterceptor interceptor = new DaoInterceptor(target, transaction);
        //一定要转换成父类类型!
        UserDaoImpl proxyInstance = (UserDaoImpl) interceptor.createProxyInstance();
        //proxyInstance.insert();
          proxyInstance.find();
    }
}

你可能感兴趣的:(JAVA设计模式)