Jdk动态代理
优点:代理可以对被代理对象通过一个invoke 方法对被代理的对象实行统一的处理。Spring AOP 实现
缺点:只能对接口进行拦截
同一个类中方法调用会导致被调用方法动态代理失败。和spring事务失效原因类似。
// 服务提供者
public interface Subject{
void doSomething();
}
public class RealSubject implements Subject{
@Override
void doSomething(){
System.out.println("真实服务!");
}
}
public class ProxyHandler implements InvocationHandler {
private Object proxied;
public ProxyHandler(Object proxied) {
this.proxied = proxied;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//在转调具体目标对象之前,可以执行一些功能处理
System.out.println("先干点");
//转调具体目标对象的方法
method.invoke( proxied, args);
System.out.println("结束了,去喝酒");
//在转调具体目标对象之后,可以执行一些功能处理
return null;
}
public static void main(String[] args) {
RealSubject real = new RealSubject();
Subject proxySubject = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(),
new Class[]{Subject.class},
new ProxyHandler(real));
proxySubject.doSomething();
Method[] methods = proxySubject.getClass().getDeclaredMethods();
Field[] fields = proxySubject.getClass().getDeclaredFields();
}
}
//生成的代理类
public class Proxy0 extends Proxy implements UserDao {
//第一步, 生成构造器
protected Proxy0(InvocationHandler h) {
super(h);
}
//第二步, 生成静态域
private static Method m1; //hashCode方法
private static Method m2; //equals方法
private static Method m3; //toString方法
private static Method m4; //...
//第三步, 生成代理方法
@Override
public int hashCode() {
try {
return (int) h.invoke(this, m1, null);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public boolean equals(Object obj) {
try {
Object[] args = new Object[] {obj};
return (boolean) h.invoke(this, m2, args);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public String toString() {
try {
return (String) h.invoke(this, m3, null);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public void save(User user) {
try {
//构造参数数组, 如果有多个参数往后面添加就行了
Object[] args = new Object[] {user};
h.invoke(this, m4, args);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
//第四步, 生成静态初始化方法
static {
try {
Class c1 = Class.forName(Object.class.getName());
Class c2 = Class.forName(UserDao.class.getName());
m1 = c1.getMethod("hashCode", null);
m2 = c1.getMethod("equals", new Class[]{Object.class});
m3 = c1.getMethod("toString", null);
m4 = c2.getMethod("save", new Class[]{User.class});
//...
} catch (Exception e) {
e.printStackTrace();
}
}
}