1.动态代理的作用:增强对象某些方法。
动态代理的角色:
1. 被代理对象(被增强对象)
2. 代理对象
3. 接口 (接口存在的意义:规定代理对象能够代理的方法)
需求: 生成一个代理对象增强ArrayList的add方法,添加成功或者添加失败都给用户提示信息。
动态代理涉及的类:
Proxy :
newProxyInstance() 生成一个对象。
ClassLoader loader : 类加载器, 直接使用当前类的类加载器即可
Class<?>[] interfaces : 代理对象要实现接口
InvocationHandler h : 处理器,
关注点: invoke方法的执行时机?
调用代理对象的任何方法都会执行一次invoke方法。
疑问: 调用代理对象任何的一个方法都调用一次invoke方法的意义在哪里?
让你自己把增强逻辑写在invoke方法里面。
总结动态代理的步骤:
1. 要维护一个被代理对象。
2. 获取当前的方法名
3. 判断当前执行方法是否是你需要增强的方法,如果是写上自己增强代码的业务逻辑
4. 如果不是需要增强的方法,使用被代理对象执行即可。
5. 不管方法是否需要增强都定义一个变量接收方法的返回结果,返回即可。
2.代码实现
public class Demo1 {
public static List getListProxy(){
List listProxy = (List) Proxy.newProxyInstance(Demo1.class.getClassLoader(), new Class[]{List.class}, new InvocationHandler() {
//被代理对象
List list = new ArrayList();
/*
method:当前调用的方法
args: 当前调用方法传递的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//1. 获取当前调用的方法的方法名
String methodName = method.getName();
//2. 判断是否为需要增强的方法,如果是需要增强的方法,让被代理对象执行当前的方法,然后加上自己业务逻辑。
Object result = null;
if("add".equalsIgnoreCase(methodName)){
result =method.invoke(list,args); //add方法是返回值
if((boolean)result){
System.out.println("添加"+args[0]+"成功了喔!");
}else{
System.out.println("添加"+args[0]+"失败了喔!");
}
}else {
//3. 如果不是增强的方法。使用被代理对象去执行当前方法即可。
result = method.invoke(list,args);
}
return result;
}
});
return listProxy;
}
public static void main(String[] args) {
List<String> list = getListProxy();
list.add("宝强");
list.add("霆锋");
list.add("乃亮");
System.out.println(list);
}
}
3.代理实现mybatis关闭会话
这里用泛型是因为不确定返回的接口是什么类型
public class DaoFactoryUtils {
/*
定义方法可以返回任意类型的Mapper接口代理对象。
使用这个方法返回代理对象的好处:使用任何方法
都会自动提交与关闭sqlSession
BrandMapper 接口,返回接口的代理对象
*/
public static <T> T getMapper(Class<T> mapperClass){
Object o = Proxy.newProxyInstance(DaoFactoryUtils.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//1. 维护一个被代理对象。
SqlSession sqlSession = MyBatisUtils.getSession();
T mapper = sqlSession.getMapper(mapperClass);
//2. 让当前方法执行
Object result = method.invoke(mapper,args);
//3. 写上自己增强代码
sqlSession.commit();
sqlSession.close();
System.out.println("=====sqlSessoin关闭l=====");
return result;
}
});
return (T) o;
}
}