1.正常接口实现
接口
public interface IUserDao { public void save(); }
实现接口
public class UserDao implements IUserDao{ @Override public void save() { System.out.println("保存入数据库成功"); } }
调用使用
//正常情况 IUserDao userDao=new UserDao(); userDao.save();
结果:
保存入数据库成功;
2.静态代理模式
接口一样:
public interface IUserDao { public void save(); }实现接口由代理类实现,初始化赋予权限,一样要实现接口
public class StaticProxy implements IUserDao{ private IUserDao userDao; public StaticProxy(IUserDao userDao) { this.userDao=userDao; } @Override public void save() { System.out.println("事务开始"); userDao.save(); System.out.println("事务结束"); } }同样是调用实现
IUserDao userDao=new UserDao(); //静态代理 StaticProxy staticProxy=new StaticProxy(userDao); staticProxy.save();
结果:
事务开始
保存入数据库成功
事务结束
优点:可以对目标功能进行扩展,实现AOP切面编程,插入代码,不影响原有功能。
缺点:要是接口有很多方法,会导致代理类很多,万一接口有变动(比如更改一个返回类型int),对应方法的代理类就要维护更新。下面的动态代理就可以解决这个问题。
3、动态代理
利用反射机制,代理类所在包:java.lang.reflect.Proxy
核心方法
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
第一个参数为类加载器,第二个为实现方法的接口,第三个是代理类
同样,还是原来的接口
public interface IUserDao { public void save(); }
原来的接口实现类
public class UserDao implements IUserDao{ @Override public void save() { System.out.println("保存入数据库成功"); } }
创建动态代理的类同时实现接口InvocationHandler,这个
是代理实例的调用处理程序 实现的接口,重写一下唯一的一个invoke方法。
public class UserProxy implements InvocationHandler{ private IUserDao userDao; public UserProxy(IUserDao userDao) { this.userDao=userDao; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("动态代理"); System.out.println("开始事务"); Object invoke = method.invoke(userDao, args); System.out.println("结束事务"); return invoke; } }
测试:
public class Test { public static void main(String[] args) { IUserDao userDao=new UserDao(); //代理情况(不用继承也可以调用接口的方法) ClassLoader classLoader = UserDao.class.getClassLoader(); IUserDao Iproxy=(IUserDao) Proxy.newProxyInstance(classLoader, UserDao.class.getInterfaces(), new UserProxy(userDao)); Iproxy.save(); } }
动态生成代理对象Iproxy,就可以调用相应的方法了。
结果:
动态代理
开始事务
保存入数据库成功
结束事务
如果改了接口返回类型为int,那么
接口:
public interface IUserDao { public int save(); }
接口实现类就这样:
public class UserDao implements IUserDao{ @Override public int save() { System.out.println("保存入数据库成功"); return 110; } }
动态代理类不变
测试类:打印一下返回值
public class Test { public static void main(String[] args) { IUserDao userDao=new UserDao(); //代理情况(不用继承也可以调用接口的方法) ClassLoader classLoader = UserDao.class.getClassLoader(); IUserDao Iproxy=(IUserDao) Proxy.newProxyInstance(classLoader, UserDao.class.getInterfaces(), new UserProxy(userDao)); int save = Iproxy.save(); System.out.println(save); } }
结果:多了个110
动态代理
开始事务
保存入数据库成功
结束事务
110
可以发现不用改动态代理的类,省事。当然,大部分情况我们都会对这些进行封装,使用就更简单了。