我其实觉得反射的内容不太重要,也不是不太重要,但是动态代理才是重中之重,之后学spring原理的时候要用到,AOP面向切面编程的原理,就是动态代理,所以回来补课了
代理模式:使用代理将对象包装起来,用该代理对象取代原始对象
首先是一个静态代理的例子
import org.junit.Test;
interface ClothFactory{
void productCloth();
}
//代理类
class ProxyClothFactory implements ClothFactory{
private ClothFactory factory;
ProxyClothFactory(ClothFactory factory){
this.factory = factory;
}
public void productCloth() {
System.out.println("代理工厂开始做事情");
factory.productCloth();
System.out.println("代理工厂结束做事情");
}
}
//被代理类
class NikeClothFactory implements ClothFactory{
public void productCloth() {
System.out.println("nike生产衣服");
}
}
public class StaticProxyTest {
@Test
public void test(){
//创建被代理类对象
ClothFactory nike = new NikeClothFactory();
//创建代理类对象
ClothFactory proxyClothFactory = new ProxyClothFactory(nike);
proxyClothFactory.productCloth();
}
}
最后运行时的结果如下,可以看到代理方法和原对象的方法全部都调用的
在静态代理中,可以看到,所有的类都在编译时确定好了,那么假如nike还需要代理鞋生产,代理裤子生产,那么你还需要写ProxyShoesFactory,ProxyPantsFactory,这样会导致代理类变得非常多,代码变得臃肿
动态代理
那么接下来写一个动态代理的例子,可以看到在这里面,实现了一个动态代理工厂ProxyFactory
调用getProxyInstance就可以拿到动态代理对象,在这里我并没有创建ProxyClothFactory,
ProxyHumanFactory等静态代理所需要的类,而是一个动态代理类全部搞定,一个类,不论是什么对象要创建代理对象都可以用这个搞定。
import org.junit.Test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Human{
String getBelief();
void eat(String food);
}
//被代理类
class SuperMan implements Human{
public String getBelief() {
return "god";
}
public void eat(String food) {
System.out.println("我吃了"+food);
}
}
/*
动态代理需要解决的问题:
1.如何根据内存中的被代理类,动态的创建一个被代理类及其对象
2.通过代理类对象调用方法时,如何去动态调用同名的方法
*/
class ProxyFactory{
//调用该方法,返回代理类对象
public static Object getProxyInstance(Object obj){
//该函数三个变量为,类加载器,该类实现的接口,以及一个Handler,
ClassLoader classLoader = obj.getClass().getClassLoader();
Class<?>[] interfaces = obj.getClass().getInterfaces();
MyInvocationHandler handler = new MyInvocationHandler(obj);
Object newProxyInstance = Proxy.newProxyInstance(
classLoader, interfaces, handler);
return newProxyInstance;
}
}
//实现一个Handler类
class MyInvocationHandler implements InvocationHandler{
private Object obj;
public MyInvocationHandler(Object obj){
this.obj=obj;
}
//当我们通过代理类的对象,调用他们的方法的时候,就会通过invoke去调用
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理开始");
Object invoke = method.invoke(obj, args);
System.out.println("动态代理结束");
return invoke;
}
}
public class ProxyTest {
@Test
public void ProxyTest(){
Human human = new SuperMan();
//proxyInstance就是代理对象
Human proxyInstance = (Human) ProxyFactory.getProxyInstance(human);
String belief = proxyInstance.getBelief();
System.out.println(belief);
proxyInstance.eat("面条");
System.out.println("********************");
ClothFactory nikeClothFactory = new NikeClothFactory();
ClothFactory nikeProxyInstance = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);
nikeProxyInstance.productCloth();
}
}
把自己实现的invoke方法中的method.invoke用try catch finally包围起来,然后在四个不同的地方插入代码块,不就是AOP的原理吗
try{
//before
method.invoke();
//afterReturning
}catch(Exception e){
//afterThrowing
}finally{
//after
}