简述代理模式中的动态代理,它的代理对象是由代码在运行过程中动态生成的,与之另外一种:静态代理,代理对象是自己创建好的类.
-
如何创建动态代理对象
-
简单的使用案例
-
两个方法中的参数
- Proxy创建代理对象的静态方法(newProxyInstance)
- InvocationHandler接口常用方法(invoke)
创建代理对象很简单,调用Proxy类的静态方法newProxyInstance(参数),传入参数即可,但是讲这个就没意思了,主要是在理解的基础上去创建会更加得心应手
- 第一个:这些参数都需要自己添加实际案例参数
Proxy类的静态方法
静态方法:static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
loader:真实对象的类加载器
-->作用:让这个方法的一个类加载运行起来,创建我们需要的代理对象
interfaces:见名知意,(接口,Class数组)真是对象的接口类型数组
-->作用:让代理对象知道,真实对象实现了哪些接口,代理对象就去实现这些接口
h:回调处理对象(这个很重要)
-->作用:拦截,过滤通过代理对象调用的方法
-->返回只一个接口,所以要使用必须创建一个实现类重写方法,或者匿名内部类实现
- 第二个:这些参数基本不用修改,但是需要在这个重写方法中会调用到这些参数
InvocationHandler接口常用方法
public Object invoke(Object proxy, Method method, Object[] args)
注意:不要手动调用该方法
作用:用来拦截代理对象方法调用(只要是通过代理对象调用方法都会被该方法拦截)
参数:
proxy:代理对象本身(不要在该方法中通过代理对象调用方法)
method:拦截到的方法
args: 代理对象调用方法时传递的参数
在理解的基础上看一看具体案例中是怎么实现的,加深理解
这是在连接池中所涉及到的
// 创建代理对象:代理连接对象conn
/*小提示:强转类型 一一对照参数:1:真实对象是连接对象那就Connection...;如果是学生那就Student... 2:实现的Connection接口一样.class;如果是学生实现Dao接口,那就Dao.class 3:匿名实现内部类方式*/
Connection proxyCon = (Connection) Proxy.newProxyInstance(
Connection.class.getClassLoader(),
new Class[]{Connection.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 判断方法是否是close方法
if(method.getName().equals("close")){
// 将代理对象添加到连接池中
list.addLast((Connection) proxy);
System.out.println("不是真正的关闭...");
return null;
}
// 调用真实对象的方法
return method.invoke(conn, args);
}
});
proxy.save(new Student());
proxy.update(new Student());
/*invoke中参数:已经介绍了,也不用修改,看看怎么用 method方法就是对最后在proxy所调用的真实对象方法拦截判断 要想调用那就method.invoke(真实对象,args(参数))*/
最后一个简单的学生代理案例
//实现的接口
public interface Dao<T>{
public void save(T t);
public void update(T t);
}
/**
业务类数据访问层:对学生进行增删改查
*/
public class StudentDao implements Dao<Student> {
// 业务方法:保存学生信息
public void save(Student stu){
System.out.println("保存学生信息");
}
// 业务方法:更新学生信息
public void update(Student stu){
System.out.println("更新学生信息");
}
}
public class Demo01 {
public static void main(String[] args){
// 创建业务对象: 真实对象
StudentDao studentDao = new StudentDao();
// 创建代理对象
Dao proxy = (Dao) Proxy.newProxyInstance(StudentDao.class.getClassLoader(),
new Class[]{Dao.class}, new InvocationHandler() {
//额外添加的方法,判断,记录
public boolean check(){
System.out.println("检查权限...");
return false;
}
public void log(){
System.out.println("记录日志...");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 检查权限
if (check()){
// 有权限则调用真实对象的方法
method.invoke(studentDao, args);
// 记录日志
log();
}
return null;
}
});
proxy.save(new Student());
proxy.update(new Student());
}
}