代理模式:是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。
简言之:在不修改源代码的前提下,对代码进行增强
静态代理
静态代码直接写吧,看代码就懂了
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
开启事务
保存数据
提交事务
以上是自己学习完总结的一些,可能有些地方说的不严谨或者错误的,希望您能帮我提出来。