java的动态代理详解
1.为什么要使用动态代理。
有时候我们在访问一个对象的时候,需要一些业务的处理,比如权限的控制,日志的记录,拦截器等等的一些面向切面的业务,这时候我们可以用拦截器实现。而且Struts的拦截器就是动态代理一个很典型的例子。
2.动态代理的使用
首先介绍几个类和方法
- Proxy类:位于java.lang.reflect.Proxy,这个类就是用于创建代理对象的核心类
- newProxyInstance方法:Proxy类的newProxyInstance方法返回代理对象 newProxyInstance(ClassLoader loader, Class< ?>[] interfaces, InvocationHandler h)
注意:为一个类创建动态代理,这个类必须实现接口,说白了,动态代理就是根据实现的接口找到类的方法做处理
//说下newProxyInstance方法的三个参数
ClassLoader loader:定义代理类的类加载器
interfaces:定义代理类所实现的接口
InvocationHandler:实现了InvocationHandler接口的类。
下面就用具体的代码说明动态代理的使用
//这个是添加用户的接口
package myexercise.proxy;
public interface UserService {
public void addUser(String userName);
public String findUser(String sql);
}
.
//添加用户的具体类,想要创建动态代理必须实现接口,这里实现了UserService接口
package myexercise.proxy;
public class UserServiceImpl implements UserService{
@Override
public void addUser(String userName) {
System.out.println("添加的用户姓名为--"+userName);
}
@Override
public String findUser(String userName) {
System.out.println("正在查询用户--"+userName);
return "查询用户成功";
}
}
.
//创建UserServiceImpl的代理类,实现执行添加用户方法的时候,输出该方法是否执行成功,类似日志记录的功能。
package myexercise.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxy implements InvocationHandler {
public Object targetObject;
public Object myProxyInstance(Object targetObject){
this.targetObject=targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始添加用户...");
Object obj=null;
try {
obj=method.invoke(method.getName(), args);
System.out.println("添加用户成功");
} catch (Exception e) {
e.printStackTrace();
System.out.println("添加用户失败");
}
return obj;
}
.
//这个是客户端类
package myexercise.proxy;
public class Client {
public static void main(String[] args) {
DynamicProxy dp=new DynamicProxy();
UserService userService=(UserService) dp.myProxyInstance(new UserServiceImpl());
userService.addUser("张三");
}
}