Aop代理
一、代理模式
代理模式(英语:Proxy Pattern)是程序设计中的一种设计模式。
所谓的代理者是指一个类别可以作为其它东西的接口。代理者可以作任何东西的接口:网上连接、存储器中的大对象、文件或其它昂贵或无法复制的资源。
代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
二、静态代理
静态代理,简单点来说就是在程序运行之前,代理类和被代理类的关系已经确定。
原因:如果不能直接修改目标类但是又想要修改目标类中的方法的实现,这时候可以使用代理类增强目标类
1、编写接口
package proxyTest;
public interface Market {
public void buy();
}
2、编写实体类
package proxyTest;
public class MarketFactory implements Market{
@Override
public void buy() {
System.out.println("采购水果中--------");
}
}
3、编写代理类
package proxyTest;
public class staticProxy implements Market{
private Market market;
public void setMarket(Market market){
this.market=market;
}
@Override
public void buy() {
System.out.println("我是代理类-------");
market.buy();
System.out.println("我可以做一些别的事情,但是不改变原有代码");
}
}
4、测试
@Test
public void test7(){
staticProxy staticProxy = new staticProxy();
staticProxy.setMarket(new MarketFactory());
staticProxy.buy();
}
/**
* OUTPUT:
* 我是代理类-------
* 采购水果中--------
* 我可以做一些别的事情,但是不改变原有代码
*/
5、缺点
如果被代理方法很多,就要为每个方法进行代理,增加了代码维护的成本。有没有其他的方式可以减少代码的维护,那就是动态代理
三、JDK动态代理
代理类在程序运行时创建的代理方式被成为动态代理。 我们上面静态代理的例子中,代理类(studentProxy)是自己定义好的,在程序运
行之前就已经编译完成。然而动态代理,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。
相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。
利用Proxy和InvocationHandler实现
**实体类:**沿用上面的Market接口及MarketFactory类
动态代理类
package proxyTest;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDkDynamicProxy implements InvocationHandler {
private Market market;
public void setMarket(Market market){
this.market=market;
}
public Market getMarket(){
/**
* Proxy.newProxyInstance:
* 参数:构造器 实现接口 InvocationHandler处理器
*
*/
return (Market) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{Market.class},this);
}
/**
* proxy:代表动态代理对象
* method:代表正在执行的方法
* args:代表调用目标方法时传入的实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用方法之前-----");
method.invoke(market,args);
buySomething();
System.out.println("调用方法之后-----");
return null;
}
public void buySomething(){
System.out.println("采购一些书籍");
}
}
测试
@Test
public void test8(){
JDkDynamicProxy jDkDynamicProxy = new JDkDynamicProxy();
jDkDynamicProxy.setMarket(new MarketFactory());
Market market = jDkDynamicProxy.getMarket();
market.buy();
}
/**
* 调用方法之前-----
* 采购水果中--------
* 采购一些书籍
* 调用方法之后-----
*/
四、JDK动态代理原理分析
1、查看动态生成的类文件
@Test
public void test8(){
JDkDynamicProxy jDkDynamicProxy = new JDkDynamicProxy();
jDkDynamicProxy.setMarket(new MarketFactory());
Market market = jDkDynamicProxy.getMarket();
market.buy();
byte[] bytes = ProxyGenerator.generateProxyClass("proxyTest", market.getClass().getInterfaces());
try {
FileOutputStream fileOutputStream = new FileOutputStream("proxyTest.compileTest.class");
fileOutputStream.write(bytes);
fileOutputStream.flush();
System.out.println("成功啦!");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
2、查看反编译的文件
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import proxyTest.Market;
public final class proxyTest extends Proxy implements Market {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
/**
* 通过反射获取对应类中的普通方法
*/
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("proxyTest.Market").getMethod("buy");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
public proxyTest(InvocationHandler var1) throws {
super(var1);//调用父类的构造方法
/**
* protected Proxy(InvocationHandler h) {
* Objects.requireNonNull(h);
* this.h = h;
* }
*/
}
/**
* 可以看到下面对所有方法重写,并都是通过super.h.invoke()来进行调用
*/
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void buy() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
}