1. 什么是代理
代理对象包含目标对象,在目标对象的基础上增加一些功能
举个例子:进行数据库操作,目标对象只需写实现即可,事务交给代理对象去做
2. 静态代理:
在不改变目标对象的情况下,对目标对象进行扩展
public interface UserDao { void delete (Long id); }
public class UserDaoImpl implements UserDao{ public void delete (Long id) { System.out.println("删除操作"); } }
public class UserDaoProxy implements UserDao{ private UserDao userDao; public UserDaoProxy(UserDao userDao) { this.userDao = userDao; } @Override public void delete(Long id) { this.startTransaction(); userDao.delete(id); this.commitTransaction(); } private void commitTransaction() { System.out.println("提交事务"); } private void startTransaction() { System.out.println("开启事务"); } }
public static void main(String[] args) { UserDaoProxy proxy = new UserDaoProxy(new UserDaoImpl()); proxy.delete(1L); }
=========输出=============
开启事务
删除操作
提交事务
缺点:代码可扩展性差,此时新增一个OrderDao,那么又要为OrderDao写一个代理类,太麻烦了。解决方法是使用动态代理
3. jdk动态代理
Jvm虚拟机在运行期间动态的创建代理类对象,因为是运行期间动态创建的,所以这个代理类对象是没有对应的java文件的
public interface UserDao { void delete (Long id); }
public class UserDaoImpl implements UserDao{ public void delete (Long id) { System.out.println("删除操作"); } }
public class TransactionManagerProxy implements InvocationHandler{ private Object target; public <T> void setTarget(T target) { this.target = target; } public <T> T getProxyObject(){ T t = (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); return t; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { this.startTransaction();//代理对象-开启事务 //target 为目标对象 Object result = method.invoke(target, args);//目标对象原有操作 this.commitTransaction();//代理对象-提交事务 return result; } private void commitTransaction() { System.out.println("提交事务"); } private void startTransaction() { System.out.println("开启事务"); } }
public static void main(String[] args) { TransactionManagerProxy proxy = new TransactionManagerProxy(); UserDao userDao = new UserDaoImpl(); proxy.setTarget(userDao); UserDao userDaoProxy = proxy.getProxyObject(); userDaoProxy.delete(1L); }
=========输出=============
开启事务
删除操作
提交事务
4. cglib动态代理
和jdk动态代理的区别是jdk动态代理的目标对象必须要有接口,而cglib则不需要,因为cglib是通过继承的方式来调用目标对象的方法
public class UserDaoImpl{ public void delete (Long id) { System.out.println("删除操作"); } }
public class TransactionManagerCglibProxy implements InvocationHandler{ private Object target; public <T> void setTarget(T target) { this.target = target; } public <T> T getProxyObject() { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass());//目标类的类型,用继承的方式进行代理 enhancer.setCallback(this);//增强处理 return (T) enhancer.create(); } private void commitTransaction() { System.out.println("提交事务"); } private void startTransaction() { System.out.println("开启事务"); } @Override public Object invoke(Object obj, Method method, Object[] args) throws Throwable { this.startTransaction(); Object result = method.invoke(target, args); this.commitTransaction(); return result; } }
public static void main(String[] args) { UserDaoImpl userDaoImpl = new UserDaoImpl(); TransactionManagerCglibProxy proxy = new TransactionManagerCglibProxy(); proxy.setTarget(userDaoImpl); UserDaoImpl userDaoProxy = proxy.getProxyObject(); userDaoProxy.delete(1L); }
=========输出=============
开启事务
删除操作
提交事务