静态代理与动态代理的区别
动态代理的角色和静态代理的一样 .
动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
基于接口的动态代理----JDK动态代理
基于类的动态代理–cglib
现在用的比较多的是 javasist 来生成动态代理 . 百度一下javasist
我们这里使用JDK的原生代码来实现,其余的道理都是一样的!
动态代理制反射 Method
Method类表示方法,类中的方法,通过Method可以执行某个方法
接口
public interface StudentsService {
/**
* 获取用户名
* @return
*/
String getName();
/**
* 获取年龄
* @return
*/
Integer getAge(Integer age);
void getNameAndAge(String name,Integer age);
}
实现类
public class UserServiceImpl implements UserService,StudentsService{
@Override
public String getName() {
System.out.println("getName");
return "getName";
}
@Override
public Integer getAge(Integer age) {
System.out.println("获得年龄:"+age);
return age;
}
@Override
public void getNameAndAge(String name, Integer age) {
System.out.println(name + "的年龄为:" + age);
}
}
@Test
public void getMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
UserServiceImpl userService = new UserServiceImpl();
Method getName = userService.getClass().getMethod("getName");
Object invoke = getName.invoke(userService);
System.out.println(invoke);
}
@Test
public void getAge() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
UserServiceImpl userService = new UserServiceImpl();
Method getName = userService.getClass().getMethod("getAge", Integer.class);
// 通过method可以执行getAge的方法的调用
/**
* 表示执行方法的调用
* 参数1: 表示对象,要执行这个对象的xxx方法
* 参数2: 方法的参数
* 返回值: Object表示方法执行后的返回值
*/
Object invoke = getName.invoke(userService,25);
System.out.println(invoke);
}
@Test
public void getNameAndAge() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
UserServiceImpl userService = new UserServiceImpl();
Method getNameAndAge = userService.getClass().getMethod("getNameAndAge", String.class, Integer.class);
// 输出:fangqing的年龄为:24
getNameAndAge.invoke(userService,"fangqing",24);
}
InvocationHandler (调用处理器)
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
- invoke()表示代理对象要执行的功能代码
- 你的代理类要完成的功能就写在invoke()方法中
- 代理类可以调用目标方法,增强功能
参数 - Object proxy : jdk创建的代理对象,无需赋值
- 目标类中的方法 , jdk提供的method对象
- 目标类中的方法参数 ,jdk提供
反射包核心类Proxy
作用:创建代理对象
方法:静态方法: newProxyInstance
参数
- ClassLoader loader : 类加载器,负责向内存中加载对象的
- 使用反射获取对象的 ClassLoader
- 比如有一个类a , a.getClass().getClassLoader()
- 这个是目标对象的类加载器
- Class<?>[] interfaces : 目标所实现的接口,也是通过反射获取的
- InvocationHandler h : 我们自己写的,代理类要完成的功能
- 返回值就是代理对象
demo实现
用户接口实现增删
public interface UserService {
/**
* 新增
*/
void add();
/**
* 删除
*/
void delete();
}
用户接口实现类
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("add");
}
@Override
public void delete() {
System.out.println("delete");
}
}
通用代理类,实现InvocationHandler
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
// 目标对象是活动的,不是固定的谁传就给谁代理
public void setTarget(Object target) {
this.target = target;
}
// 创建代理类
public Object getProxy() {
// 类加载器为:sun.misc.Launcher$AppClassLoader@b4aac2
// 代理接口为:[Ljava.lang.Class;@15a1588
// 调用处理器为:com.example.动态代理.ProxyInvocationHandler@1116ca2
System.out.println("类加载器为:"+this.getClass().getClassLoader());
System.out.println("代理接口为:"+target.getClass().getInterfaces());
System.out.println("调用处理器为:"+ this);
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
}
// 通过代理对象调用功能方法时,便会执行此方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 功能增强
log(method.getName());
// 调用目标对象的方法
Object result = method.invoke(target,args);
return result;
}
public void log(String methodName){
System.out.println("执行了" + methodName + "方法");
}
}
@Test
public void test() {
UserServiceImpl userServiceImpl = new UserServiceImpl();
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
proxyInvocationHandler.setTarget(userServiceImpl);
UserService proxy = (UserService) proxyInvocationHandler.getProxy();
proxy.add();
// 输出结果为:
//类加载器为:sun.misc.Launcher$AppClassLoader@b4aac2
//代理接口为:[Ljava.lang.Class;@15a1588
//调用处理器为:com.example.动态代理.ProxyInvocationHandler@1116ca2
//执行了add方法
//add
}