静态代理,动态代理简单理解

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

简言之:在不修改源代码的前提下,对代码进行增强

静态代理

静态代码直接写吧,看代码就懂了

public interface UserDao {
    
    
    public void save();
}
public class UserDaoImpl implements UserDao{
    
    
    @Override
    public void save() {
    
    
        System.out.println("保存数据");
    }
}
public class UserDaoProxy implements UserDao{
    
    

    private UserDao userDao;

    public UserDaoProxy(UserDao userDao){
    
    
        this.userDao = userDao;
    }
    @Override
    public void save() {
    
    
        System.out.println("开启事务");
        userDao.save();
        System.out.println("事务提交");
    }
}
public class Test {
    
    
    public static void main(String[] args) {
    
    
        UserDao userDao = new UserDaoProxy(new UserDaoImpl());
        System.out.println(userDao.getClass());
        userDao.save();
    }
}

测试结果

class com.UserDaoProxy
开启事务
保存数据
事务提交

从上面代码很容易看出它的缺点:

1.冗余---由于代理对象要实现与目标对象一致的接口,会产生过多的代理类。
2.不易维护---一旦接口增加方法,目标对象与代理对象都要进行修改。

动态代理

静态代理与动态代理的区别主要在:

1.静态代理在编译时就已经实现,编译完成后代理类是一个实际的class文件
2.动态代理是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中

分类:

jdk动态代理:基于接口的动态代理(被代理类至少实现一个接口,如果没有则不能使用)
CGLib代理:    基于子类的动态代理(被代理类不能是最终类)

下面简单说一下JDK动态代理
创建代理对象-------使用Proxy类中的newProxyInstance方法

    public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

newProxyInstance方法的参数介绍

ClassLoader:类加载器------它是用于加载代理对象字节码的,和被代理对象使用相同的类加载器,固定写法

Class[] 字节码数组------它是用于让代理对象和被代理对象有相同的方法,固定写法

InvocationHandler 用于提供增强的代码------让我们写如何代理

下面举个例子(被代理类还是上面的)

public class DynStaticFactory {
    
    

    private Object target;// 维护一个目标对象

    public DynStaticFactory(Object target) {
    
    
        this.target = target;
    }
    // 为目标对象生成代理对象
    public Object getProxyInstance() {
    
    
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
		target.getClass().getInterfaces(), new InvocationHandler() {
    
    
            /**
             * 执行被代理对象的任何接口方法时都会经过该方法
             * @param proxy 代理对象的引用
             * @param method 当前执行的方法
             * @param args 当前执行方法所需要的参数
             * @return 和被代理对象有相同的返回值
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method,
			Object[] args) throws Throwable {
    
    
                System.out.println("开启事务");
                // 执行目标对象方法
                Object returnValue = method.invoke(target, args);
                System.out.println("提交事务");
                return null;
            }
        });
    }
}


public class TestDyn {
    
    
    public static void main(String[] args) {
    
    
        DynStaticFactory dynStaticFactory = new DynStaticFactory(new UserDaoImpl());
        UserDao userDao = (UserDao)dynStaticFactory.getProxyInstance();
        System.out.println(userDao.getClass());
        userDao.save();
    }
}

测试结果

class com.sun.proxy.$Proxy0
开启事务
保存数据
提交事务

以上是自己学习完总结的一些,可能有些地方说的不严谨或者错误的,希望您能帮我提出来。

猜你喜欢

转载自blog.csdn.net/weixin_43733952/article/details/99297471