春の基礎となる原則の、AOPの実装
春AOPの基礎となる原則は、Javaの動的プロキシ技術。
第二に、動的プロキシ
原則
実行時には、何らかの方法で動的に生成されたプロキシクラスの.classファイルは、技術は比較的一般的とCGLIB JAVAダイナミックプロキシエージェントです。
分類
JAVAダイナミックエージェント技術
あなたは、インターフェイスを定義する必要があります
public interface Animal {
void eat(String food);
}
复制代码
実装クラスキャット
public class Cat implements Animal {
@Override
public void eat(String food) {
System.out.println(Cat.class.getSimpleName()+" eat:"+food);
}
}
复制代码
実装クラスの犬
public class Dog implements Animal {
@Override
public void eat(String food) {
System.out.println(Dog.class.getSimpleName()+" eat:"+food);
}
}
复制代码
public class AnimalHandler implements InvocationHandler {
private Animal target;
public AnimalHandler(Animal target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
//这里可以修改参数
StringBuilder stringBuilder=new StringBuilder();
for (int i = 0; i < args.length; i++) {
stringBuilder.append("param"+(i+1)+":"+args[i]).append(",");
}
if (stringBuilder.length()>1){
System.out.println(stringBuilder.subSequence(0,stringBuilder.length()-1));
}
System.out.println("method:"+method.getName());
Object ret=method.invoke(target,args);
after();
return ret;
}
/**
* 方法执行前
*/
private void before() {
System.out.println("方法执行前 !");
}
/**
* 方法执行后
*/
private void after() {
System.out.println("方法执行后");
}
}
复制代码
テストは、プロキシクラスを生成します
public static void main(String[] args) {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
Animal cat = new Cat();
//找到代理对象
Animal catProxy = (Animal) Proxy.newProxyInstance(Cat.class.getClassLoader(), new Class[]{Animal.class}, new AnimalHandler(cat));
System.out.println(catProxy.getClass().getSimpleName());
catProxy.eat("猫粮");
Animal dog = new Dog();
Animal dogProxy = (Animal) Proxy.newProxyInstance(Dog.class.getClassLoader(), new Class[]{Animal.class}, new AnimalHandler(dog));
System.out.println(dogProxy.getClass().getSimpleName());
dogProxy.eat("狗粮");
}
复制代码
出力:
$Proxy0
方法执行前 !
param1:猫粮
method:eat
Cat eat:猫粮
方法执行后
$Proxy0
方法执行前 !
param1:狗粮
method:eat
Dog eat:狗粮
方法执行后
复制代码
System.getProperties()。(「sun.misc.ProxyGenerator.saveGeneratedFiles」、「真」)に入れ、この文は地元紙にプロキシクラスを生成します。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.sun.proxy;
import com.yuntian.firstspringboot.proxy.Animal;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements Animal {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
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 eat(String var1) throws {
try {
super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
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);
}
}
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("com.yuntian.firstspringboot.proxy.Animal").getMethod("eat", Class.forName("java.lang.String"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
复制代码
- プロキシクラスのオブジェクトを生成します
Proxy.newProxyInstance(Cat.class.getClassLoader(), new Class[]{Animal.class}, new AnimalHandler(cat));
复制代码
- プロキシクラスを見ると、キャッシュを探し始めます
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
Class<?> cl = getProxyClass0(loader, intfs);
复制代码
このコードが実行されると上記の方法の分析は、ClassLoaderクラスローダは、クラスインターフェースハンドラ実装クラスパラメータ。ソースコード解析、プロキシクラスを生成することがわかっている場合、完全に界面を得る方法を反射し、メソッドを実装し、h.invokeスルー()メソッドは、元のオブジェクトのメソッドを呼び出します。
CGLIBダイナミックエージェント技術
ここでは、クラスやインタフェースを定義することができます
public abstract class AbstartAnimal {
public abstract void eat(String food);
}
复制代码
public class CatTest extends AbstartAnimal {
@Override
public void eat(String food) {
System.out.println(CatTest.class.getSimpleName()+" eat:"+food);
}
}
复制代码
public class DogTest extends AbstartAnimal {
@Override
public void eat(String food) {
System.out.println(DogTest.class.getSimpleName()+" eat:"+food);
}
}
复制代码
定義方法インターセプタ
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class AbstratAnimalInterceptor implements MethodInterceptor {
/**
* 被增强的类
*/
private AbstartAnimal target;
public AbstratAnimalInterceptor(AbstartAnimal target) {
super();
this.target = target;
}
/**
* 用来产生代理对象
*/
public Object createProxy() {
// 增强类
Enhancer enhancer = new Enhancer();
// 设置增强类的回调方法
enhancer.setCallback(this);
//设置代理类的父类
enhancer.setSuperclass(AbstartAnimal.class);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
Object ret = method.invoke(target, objects);
after();
return ret;
}
/**
* 方法执行前
*/
private void before() {
System.out.println("方法执行前 !");
}
/**
* 方法执行后
*/
private void after() {
System.out.println("方法执行后");
}
}
复制代码
試験方法:
@Test
public void testcglibProxy() {
AbstartAnimal cat = new CatTest();
AbstratAnimalInterceptor interceptorCat = new AbstratAnimalInterceptor(cat);
AbstartAnimal catProxy = (AbstartAnimal) interceptorCat.createProxy();
catProxy.eat("猫粮");
AbstartAnimal dog = new DogTest();
AbstratAnimalInterceptor interceptorDog = new AbstratAnimalInterceptor(dog);
AbstartAnimal dogProxy = (AbstartAnimal) interceptorDog.createProxy();
dogProxy.eat("狗粮");
}
复制代码
出力:
方法执行前 !
CatTest eat:猫粮
方法执行后
方法执行前 !
DogTest eat:狗粮
方法执行后
复制代码
第三に、比較プロキシモード
要因の比較 | JAVA動的プロキシ | CGLIBエージェント |
---|---|---|
使いやすいです | 便利 | 便利 |
生成モード | ダイナミックなバイトコード | ダイナミックなバイトコード |
発電効率 | 13msの/ A | 217ms / A |
業務の効率化 | 2224ミリ秒、634022トン/秒 | 1123ミリ秒、1255623トン/秒 |
のみJAVA CGLIB動的プロキシエージェントのばねエージェント技術と、他にも、プロキシベースの技術JAVAASSISTとASMを生成します。