代理某个类操作,该代理类需要实现跟被代理类同样的接口。
1.定义一个接口。
public interface IOper { public void run(); }
2.被代理类需要实现上面的接口
public class TrueOper implements IOper{ public void run(){ System.out.println("奔跑吧少年---"); } }
3.建立一个handle
/** Processes a method invocation on a proxy instance and returns
* the result. This method will be invoked on an invocation handler
* when a method is invoked on a proxy instance that it is
* associated with.
*/
//代理类的每个方法会转到该handle的invoke方法
public class OperHandler implements InvocationHandler{ private TrueOper oper; public OperHandler(TrueOper oper){ this.oper = oper; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("-------before--------"); Object obj = method.invoke(oper, args);
System.out.println("-------after----------");
return obj;
}
}
4.测试
public class TestProxy { public static void main(String[] args) { IOper proxyOper = (IOper)Proxy.newProxyInstance(IOper.class.getClassLoader(), new Class[]{IOper.class}, new OperHandler(new TrueOper())); proxyOper.run(); } }
原理: 在运行期间,proxyOper会动态生成一个class类,该类实现了IOper接口,代理类的每个方法都会调用OperHandler的invoker方法。
5: 一般该模式在系统架构中用到, 比如spring和mybatis结合时,用到sqlSession时,
SqlSessionTemplate有个例子
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) { notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required"); notNull(executorType, "Property 'executorType' is required"); this.sqlSessionFactory = sqlSessionFactory; this.executorType = executorType; this.exceptionTranslator = exceptionTranslator; this.sqlSessionProxy = (SqlSession) newProxyInstance( SqlSessionFactory.class.getClassLoader(), new Class[] { SqlSession.class }, new SqlSessionInterceptor()); } /** * Proxy needed to route MyBatis method calls to the proper SqlSession got * from Spring's Transaction Manager * It also unwraps exceptions thrown by {@code Method#invoke(Object, Object...)} to * pass a {@code PersistenceException} to the {@code PersistenceExceptionTranslator}. */ private class SqlSessionInterceptor implements InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { final SqlSession sqlSession = getSqlSession( SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator); try { Object result = method.invoke(sqlSession, args); if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) { // force commit even on non-dirty sessions because some databases require // a commit/rollback before calling close() sqlSession.commit(true); } return result; } catch (Throwable t) { Throwable unwrapped = unwrapThrowable(t); if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) { Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped); if (translated != null) { unwrapped = translated; } } throw unwrapped; } finally { closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); } } }