AOP详解-动态代理实现AOP
1. 什么是动态代理
- 动态代理实际上就是 Java 中的一个方法,可以动态创建一组指定接口的实现对象(在运行时创建)
interface A {}
interface B {}
//obj对象的类型实现了A和B两个接口
Object obj = 方法(new Class[]{A.class, B.class})
2. 动态代理的使用
- 代码:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces, InvocationHandler h)- ClassLoader loader: 方法需要动态生成一个类,这个类实现A、B两个接口,然后创建这个类的对象。这个生成的类需要加载到方法区中,因此需要一个 ClassLoader 来加载这个类
- Class<?>[] interfaces: 需要代理对象实现的数组
- InvocationHandler h: 调用处理器
public void test3() {
// 代理对象实现的所有接口中的方法,内容都是调用InvocationHandler的invoke()方法
ClassLoader classLoader = this.getClass().getClassLoader();
//这里创建一个空实现的调用处理器。
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("你好!!!!");
return "Hello";//这里改为返回"Hello"
}
};
Object obj = Proxy.newProxyInstance(classLoader, new Class[]{A.class, B.class}, invocationHandler);
//强转为A和B接口类型,说明生成的代理对象实现了A和B接口
A a = (A) obj;
B b = (B) obj;
a.toString();//注意这里调用了toString()方法
b.getClass();//注意这里调用了getClass()方法
//这里在A接口中添加了一个方法public Object aaa(String s1, int i);
Object hello = a.aaa("Hello", 100);
System.out.println(obj.getClass());//这里看一下代理对象是什么
System.out.println(hello);//这里看一下返回值是什么
} - invoke 方法
3. 初步实现 AOP
接口
package demo2;
//服务生
public interface Waiter {
//服务方法
public void server();
}接口实现类
package demo2;
public class ManWaiter implements Waiter {
@Override
public void server() {
System.out.println("服务中");
}
}动态代理进行增强
package demo2;
import org.junit.Test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Demo2 {
@Test
public void test1() {
Waiter waiter = new ManWaiter();
waiter.server();
}
@Test
public void test2() {
Waiter manWaiter = new ManWaiter();
ClassLoader classLoader = this.getClass().getClassLoader();
Class[] interfaces = {Waiter.class};
InvocationHandler invocationHandler = new WaiterInvocationHandler(manWaiter);
//得到代理对象,代理对象就是在目标对象的基础上进行了增强的对象
Waiter waiter = (Waiter) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
waiter.server();//前面添加“你好”,后面添加“再见”
}
}
class WaiterInvocationHandler implements InvocationHandler {
private Waiter waiter;
WaiterInvocationHandler(Waiter waiter) {
this.waiter = waiter;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("你好");
waiter.server();//调用目标对象的方法
System.out.println("再见");
return null;
}
}
4. 完善的 AOP 实现
前置增强接口
/**
* 前置增强
*/
public interface BeforeAdvice {
public void before();
}后置增强接口
public interface AfterAdvice {
public void after();
}代理对象产生代码封装
package demo3;
import com.sun.org.apache.regexp.internal.RE;
import org.junit.After;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 1、创建代理工厂
* 2、给工厂设置目标对象、前置增强、后置增强
* 3、调用creatProxy()得到代理对象
* 4、执行代理对象方法时,先执行前置增强,然后是目标方法,最后是后置增强
*/
//其实在Spring中的AOP的动态代理实现的一个织入器也是叫做ProxyFactory
public class ProxyFactory {
private Object targetObject;//目标对象
private BeforeAdvice beforeAdvice;//前值增强
private AfterAdvice afterAdvice;//后置增强
/**
* 用来生成代理对象
* @return
*/
public Object creatProxy() {
/**
* 给出三个参数
*/
ClassLoader classLoader = this.getClass().getClassLoader();
//获取当前类型所实现的所有接口类型
Class[] interfaces = targetObject.getClass().getInterfaces();
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/**
* 在调用代理对象的方法时,会执行这里的内容
*/
if(beforeAdvice != null) {
beforeAdvice.before();
}
Object result = method.invoke(targetObject, args);//调用目标对象的目标方法
//执行后续增强
afterAdvice.after();
//返回目标对象的返回值
return result;
}
};
/**
* 2、得到代理对象
*/
Object proxyObject = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
return proxyObject;
}
//get和set方法略
}将相关参数注入到 ProxyFactory 后就可以通过 createProxy() 方法获取代理对象
package demo3;
import org.junit.Test;
public class Demo3 {
@Test
public void tset1() {
ProxyFactory proxyFactory = new ProxyFactory();//创建工厂
proxyFactory.setTargetObject(new ManWaiter());//设置目标对象
//设置前置增强
proxyFactory.setBeforeAdvice(new BeforeAdvice() {
@Override
public void before() {
System.out.println("客户你好");
}
});
//设置后置增强
proxyFactory.setAfterAdvice(new AfterAdvice() {
@Override
public void after() {
System.out.println("客户再见");
}
});
Waiter waiter = (Waiter) proxyFactory.creatProxy();
waiter.server();
}
}