经典AOP-基于代理

来源:互联网 发布:程序员的数学2pdf 编辑:程序博客网 时间:2024/06/05 11:50

基于代理是一项非常经典的具有AOP思想的实现方法,从这也产生了代理模式。代理其实就是跟委托实现同一个的接口(这是弊端,想要代理就必须有接口),其实现方式有两种,静态代理和动态代理。在Java中,安全、日志、事务都是AOP应用的实际方面。

静态代理

静态代理的实现是指通过自己手动的生成一个代理对象,并调用代理对象的方法,静态代理思想也很好地体现了动态代理的思想精髓。下面是一个日志的静态代理。

首先声明一个接口,这个接口是委托和代理都需要实现的

public interface IDao<T extends Serializable> {/** * 将obj保存到数据库表 * @param obj,要保存到数据库的实体对象 */public void doSave(T obj);}

为了更好地模拟ORM,我们需要定义简单的实体类

实体类接口

public interface IEntity<T extends Serializable> extends Serializable {public T getId();}

实体类Book

public class Book implements IEntity<Integer>{private Integer id;public Integer getId() {// TODO Auto-generated method stubreturn id;}}

定义委托——BookDao

public class BookDao implements IDao<Book> {public void doSave(Book obj) {// TODO Auto-generated method stub//将对象保存到数据库表}}

定义代理

public class BookDaoProxy implements IDao<Book> {/** * 代理依赖于委托 */private BookDao dao;public BookDao getDao() {return dao;}/** * 注入委托 * @param dao,需要注入的委托实例 */public void setDao(BookDao dao) {this.dao = dao;}public void doSave(Book obj) {// TODO Auto-generated method stubSystem.out.println("开始记录日志");dao.doSave(obj);System.out.println("结束记录日志");}}

这样子,在实际调用的时候,调用BookDaoProxy类的doSave方法,就不仅能完成委托类的保存实体到数据库这以功能,还能够实现日志记录功能。

动态代理

动态代理的实现,是要与Java官方提供的接口InvocationHandler相关联。

这个接口里面有一个方法:

public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// TODO Auto-generated method stubreturn null;}

其中,proxy参数是代理的实例,不要误当做是委托实例,而method是委托的方法实例,args是方法参数,学过java反射的都知道,通过反射来调用方法method.invoke(对象实例,参数),由于没有找到委托实例,所以在实现这个接口的时候,我们要在实现类中注入一个委托实例。
public class BookDaoProxy implements InvocationHandler {/** * 将要注入的委托实例 */private Object target;public Object bind(Object target){this.target = target;return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// TODO Auto-generated method stubSystem.out.println("开始记录日志");Object result = method.invoke(target, args);System.out.println("结束记录日志");return result;}}

bind方法可以根据委托来得到一个代理实例,而接口中的Invoke方法内部的实现还是主要依赖于java的反射。

BookDao bookDao = new BookDao();BookDaoProxy proxy = new BookDaoProxy();bookDao = (BookDao) proxy.bind(bookDao);bookDao.doSave(new Book());

这样,就将代理掩饰成为委托并调用,但实际上执行了代理的doSave方法。



0 0
原创粉丝点击