Ethon

为什么要有方法,因为懒惰是一种美德。

   :: 首页  :: 新随笔  ::  ::  :: 管理

代理模式:是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。

示例:火车票代售就是代理模式的体现,我们可以从火车票代售点买火车票,代售点代理了火车站对象,提供了买火车票的方法

 

 

 一:静态代理

  • 前提:需要代理对象和目标对象实现一样的接口
  • 优点:可以在不修改目标对象的前提下,扩展目标对象的功能
  • 缺点:如果目标对象的方法发生改变,比如方法名做了修改,则代理类也要做修改
/**
 * 接口
 * @author Ethon
 *
 */
public interface Person {

    void add();

}
/**
 * 目标对象
 * @author Ethon
 *
 */
public class Student implements Person {
    
    @Override
    public void add() {
            System.out.println("这是目标对象中的add()方法");
    }
}
/**
 * 代理对象
 * @author Ethon
 *
 */
public class StudentProxy implements Person{
    
    //目标对象
    private Student student;
    
    public StudentProxy(Student student){
        this.student = student;
    }

    @Override
    public void add() {
        System.out.println("开启事务..."); // 扩展功能
        student.add();
        System.out.println("提交事务...");
    }
}
/**
 * 测试类
 * @author Ethon
 *
 */
public class Test {
    
    public static void main(String[] args){
        //目标对象
        Student student = new Student();
        //代理对象
        StudentProxy proxy = new StudentProxy(student);
        proxy.add();
    }
}

输出结果:

开启事务...
这是目标对象中的add()方法
提交事务...

 ----------------------------------------------------------  分隔线  ----------------------------------------------------------

二、动态代理

代理类在程序运行时创建的代理方式被成为动态代理,动态代理对象不需要实现接口,但目标对象必须实现接口。

       静态代理与动态代理的区别:

  • 静态代理在编译时就已经实现,编译完成后代理类就是一个实际的class文件
  • 动态代理在运行时动态生成字节码,并加载到jvm中

JDK的动态代理:在java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成JDK动态代理类和动态代理对象。

/**
 * 接口
 * @author Ethon
 *
 */
public interface Person {

    void add();

}
/**
 * 目标对象
 * @author Ethon
 *
 */
public class Student implements Person {
    

    @Override
    public void add() {
            System.out.println("这是目标对象中的add()方法");
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * @author Ethon
 *
 */
public class StuInvocationHandler implements InvocationHandler{
    //目标对象
    private Object target;
    
    public StuInvocationHandler(Object target){
        this.target = target;
    }

    /**
     * proxy: 动态代理对象
     * method:正在执行的方法
     * args:调用目标方法时传入的实参
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开启事务..."); // 扩展功能
        Object obj = method.invoke(target, args);
        System.out.println("提交事务...");
        return obj;
    }
}
/**
 * 测试类
 * @author Ethon
 *
 */
public class Test {
    
    public static void main(String[] args){
        //目标对象
        Person student = new Student();
        //创建一个与代理对象相关联的InvocationHandler
        InvocationHandler handler = new StuInvocationHandler(student);
        //得到代理对象
        Person studentProxy = (Person) Proxy.newProxyInstance(Student.class.getClassLoader(), Student.class.getInterfaces(), handler);
        studentProxy.add(); 
    }
}

输出结果:

开启事务...
这是目标对象中的add()方法
提交事务...

----------------------------------------------------------  分隔线  ----------------------------------------------------------

 cglib的动态代理:CGLib动态代理是代理类去继承目标类,然后重写其中目标类的方法。

/**
 * 业务类
 * @author Ethon
 *
 */
public class Student {
    
    /**
     * 该方法不能被子类覆盖,cglib是无法代理final修饰的方法的
     */
    final public void sing(){
        System.out.println("sing...");
    }

    public void study(){
        System.out.println("study...");
    }
}
import java.lang.reflect.Method;

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

/**
 * 方法拦截器
 * @author Ethon
 *
 */
public class MyMethodInterceptor implements MethodInterceptor{

    /**
     * obj:表示增强的对象,即实现这个接口类的一个对象
     * method:表示要被拦截的方法
     * args:表示要被拦截方法的参数
     * proxy:表示要触发父类的方法对象
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("开启事务..."); //扩展功能
        Object object = proxy.invokeSuper(obj, args);
        System.out.println("提交事务...");
        return object;
    }
}
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;

/**
 * 测试类
 * @author Ethon
 *
 */
public class Test {
    public static void main(String[] args){
        //代理类class文件存入本地磁盘
        //System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D\\code");
        //通过cglib动态代理获取代理对象的过程
        Enhancer enhancer = new Enhancer();
        //设置enhancer对象的父类
        enhancer.setSuperclass(Student.class);
        //设置enhancer的回调对象
        enhancer.setCallback(new MyMethodInterceptor());
        //创建代理对象
        Student stuProxy = (Student) enhancer.create();
        //通过代理对象调用目标方法
        //调用方法时,在代理类中会先判断是否实现了方法拦截的接口,如果实现了那就会被方法拦截器拦截,没实现的话直接调用目标类的方法
        stuProxy.study();
    }
}

输出结果:

开启事务...
study...
提交事务...

 

posted on 2020-11-14 20:26  Ethon  阅读(142)  评论(0编辑  收藏  举报