Javaエージェントの3つの実装を浅くする
注意:本文のすべてのclassで使用するstatic修飾は主に1つのクラスでテストできるようにするためです.実際のプロジェクトではそうすべきではなく、classを分けるべきだ.文字の説明はそんなに多くないので、コードを見たほうが分かりやすいでしょう...
1.Javaエージェントの理解
2.エージェントモードの実現
2.1静的エージェント
2.1.0メリットとデメリットの利点:必要なメソッドに対してのみエージェントロジックを追加します. 欠点:1.エージェントのたびにエージェントクラスを実装する必要があります.2.エージェントクラスは機能が固定されており、柔軟に変更できない.3.プロジェクトには多くのエージェントのコードがあり、ターゲットオブジェクトが変更された場合、エージェントクラスも変更に対応する必要があり、コードのメンテナンスに不利である.
2.1.1実現方式一:継承エージェント(継承方式実現エージェント)
2.1.2実装方式2:集約方式(同じインタフェースを実装することによって)
集約方式を使用すると、他のエージェントオブジェクトを追加して、すでにエージェントされているオブジェクトに対して拡張エージェントを続行することもできます.
2.2動的エージェント(JDKエージェント)
JDKオリジナルダイナミックエージェントはJavaオリジナルサポートであり、外部依存は必要ありませんが、
2.2.0メリットとデメリットの利点:動的エージェントのすべてのインタフェース. の欠点:エージェントを実装するためにインタフェース方式を使用することに依存しなければならない.
主な実装はJDKが持つProxyクラスを用いて実現する.
Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.
動的エージェントは,メソッドを逐一エージェントする必要がなく,すべてのインタフェースメソッドを反射サイクルすることによって,動的にエージェントロジックを加える.メソッドの名前を実行することで、現在のメソッドにエージェントが必要かどうかをフィルタすることもできます.
2.2.1基本実装方式
2.2.2動的エージェントの最適化
JDK Proxy動的エージェントのさらなる最適化:抽象出代理親 エージェントクラスは、独自のbeforeおよびafterメソッド を実装する.
2.3 Cglibエージェント
2.3.0メリットとデメリット利点:Cglibエージェントはインタフェースに依存せず、JDKエージェントはインタフェース に依存する.欠点: SpringのAOPプログラミングでは、コンテナに加入するターゲットオブジェクトに実装インタフェースがある場合、JDKエージェント を使用する.ターゲットオブジェクトがインタフェースを実装していない場合、Cglibエージェント を使用する.
2.3.1 spring-coreによるcglibエージェントの実装
spring-coreを参照する必要があります.jarSpring Core » 5.1.8.RELEASE
2.3.1 spring-coreによるcglibエージェントの実装(バージョンの最適化)
主な最適化点:抽象共通ProxyFactoryクラス を抽出特定のエージェントクラスの実装はProxyFactory から継承される.
3.Refs API java.lang.reflect.Proxy Spring Core » 5.1.8.RELEASE javaの3つのエージェントモード を理解する javaエージェント Javaエージェントと動的エージェントメカニズムの分析と応用 Java ProxyとCGLIBダイナミックエージェント原理
1.Javaエージェントの理解
は、単純に言えば、ソースコードを変更することなく、ターゲットオブジェクトに対する機能拡張を実現する
である.使用シーン:メソッドの実行前後に実行時間を計算したり、ログを記録したりします.これらの機能の拡張は、元のコードを変更することなく実現される.2.エージェントモードの実現
2.1静的エージェント
2.1.0メリットとデメリット
2.1.1実現方式一:継承エージェント(継承方式実現エージェント)
public class StaticProxyByExtendTest {
//
public static class UserServiceImpl {
public void login(String username, String pwd) {
System.out.println("Welcome " + username);
}
}
//
public static class UserServiceImplProxy extends UserServiceImpl{
public void login(String username, String pwd) {
System.out.println("before.... ");//
super.login(username, pwd);//
System.out.println("after.... ");//
}
}
//
public static void main(String[] args) {
UserServiceImpl ee = new UserServiceImplProxy();
ee.login("Stephen", "123");
}
}
2.1.2実装方式2:集約方式(同じインタフェースを実装することによって)
public class StaticProxyByGroupTest {
public interface UserService {
public void login(String username, String pwd);
}
//
public static class UserServiceImpl implements UserService {
@Override
public void login(String username, String pwd) {
System.out.println("Welcome " + username);
}
}
//
public static class UserServiceImplProxy implements UserService {
private UserService userService;
public UserServiceImplProxy(UserService userService) {
this.userService = userService;
}
@Override
public void login(String username, String pwd) {
System.out.println("before.... ");//
userService.login(username, pwd);//
System.out.println("after.... ");//
}
}
public static void main(String[] args) {
UserService target = new UserServiceImpl();
UserService tt = new UserServiceImplProxy(target);
tt.login("Stephen", "123");
}
}
集約方式を使用すると、他のエージェントオブジェクトを追加して、すでにエージェントされているオブジェクトに対して拡張エージェントを続行することもできます.
2.2動的エージェント(JDKエージェント)
JDKオリジナルダイナミックエージェントはJavaオリジナルサポートであり、外部依存は必要ありませんが、
のみでエージェントを行うことができます.2.2.0メリットとデメリット
主な実装はJDKが持つProxyクラスを用いて実現する.
newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h)
Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.
動的エージェントは,メソッドを逐一エージェントする必要がなく,すべてのインタフェースメソッドを反射サイクルすることによって,動的にエージェントロジックを加える.メソッドの名前を実行することで、現在のメソッドにエージェントが必要かどうかをフィルタすることもできます.
2.2.1基本実装方式
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxyByJDKTest {
public interface UserService {
public void login(String username, String pwd);
}
//
public static class UserServiceImpl implements UserService {
@Override
public void login(String username, String pwd) {
System.out.println("Welcome " + username);
}
}
// 1
public static class UserServiceImplProxy {
private UserService userServiceProxy;
public UserServiceImplProxy(UserService userService) {
// JDK UserService
UserService proxy = (UserService) Proxy.newProxyInstance(
userService.getClass().getClassLoader(), //1.
userService.getClass().getInterfaces(), // 2. ,
new InvocationHandler() { // 3.
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before.... ");//
Object returnValue = method.invoke(userService, args);
System.out.println("after.... ");//
return returnValue;
}
});
this.userServiceProxy = proxy;
}
public UserService getProxy() {
return this.userServiceProxy;
}
}
//
@SuppressWarnings("unchecked")
public static T getJDKProxy(T t) {
T proxy = (T) Proxy.newProxyInstance(
t.getClass().getClassLoader(),
t.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before.... ");//
Object returnValue = method.invoke(t, args);
System.out.println("after.... ");//
return returnValue;
}
});
return proxy;
}
public static void main(String[] args) {
UserService target = new UserServiceImpl();
// 1
UserServiceImplProxy proxy = new UserServiceImplProxy(target);
proxy.getProxy().login("Stephen", "123");
//
UserService jdkProxy = getJDKProxy(target);
jdkProxy.login("JDK Stephen", "123");
}
}
2.2.2動的エージェントの最適化
JDK Proxy動的エージェントのさらなる最適化:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxyByJDKTest2 {
//
public interface UserService {
public void login(String username, String pwd);
}
//
public static class UserServiceImpl implements UserService {
@Override
public void login(String username, String pwd) {
System.out.println("Welcome " + username);
}
}
//
public static class UserServiceImplProxy extends JDKProxy {
public UserService userServiceProxy;
public UserServiceImplProxy(UserService userService) {
this.userServiceProxy = getJDKProxy(userService);
}
@Override
protected void before(Method method) {
System.out.println("before.... ");//
}
@Override
protected void after(Method method) {
System.out.println("after.... ");//
}
}
//Common proxy object class
public static abstract class JDKProxy {
protected abstract void before(Method method);
protected abstract void after(Method method);
@SuppressWarnings("unchecked")
protected T getJDKProxy(T t) {
T proxy = (T) Proxy.newProxyInstance(
t.getClass().getClassLoader(),
t.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before(method);//
Object returnValue = method.invoke(t, args);
after(method);//
return returnValue;
}
});
return proxy;
}
}
public static void main(String[] args) {
UserService target = new UserServiceImpl();
//
UserServiceImplProxy proxy = new UserServiceImplProxy(target);
proxy.userServiceProxy.login("Stephen", "123");
}
}
2.3 Cglibエージェント
CGLIB
(Code GenerationLibrary)はASMベースのバイトコード生成ライブラリであり、実行時にバイトコードを修正し、動的に生成することができます.CGLIB , , final 。
2.3.0メリットとデメリット
2.3.1 spring-coreによるcglibエージェントの実装
spring-coreを参照する必要があります.jarSpring Core » 5.1.8.RELEASE
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class DynamicProxyBySpringCglibTest {
//
public interface UserService {
public void login(String username, String pwd);
}
//
public static class UserServiceImpl implements UserService {
@Override
public void login(String username, String pwd) {
System.out.println("Welcome " + username);
}
}
//
public static class ProxyFactory implements MethodInterceptor {
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
public Object getProxyInstance(){
//1. Enhancer 、
Enhancer en = new Enhancer();
//2.
en.setSuperclass(target.getClass());
//3.
en.setCallback(this);
//4. ( )
return en.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("before.... ");//
Object returnValue = method.invoke(target, args);
System.out.println("after.... ");//
return returnValue;
}
}
public static void main(String[] args) throws Exception {
UserService target = new UserServiceImpl();
UserService proxy = (UserService) new ProxyFactory(target).getProxyInstance();
proxy.login("Stephen", "123");
}
}
2.3.1 spring-coreによるcglibエージェントの実装(バージョンの最適化)
主な最適化点:
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class DynamicProxyBySpringCglibTest1 {
//
public interface UserService {
public void login(String username, String pwd);
}
//
public static class UserServiceImpl implements UserService {
@Override
public void login(String username, String pwd) {
System.out.println("Welcome " + username);
}
}
//Common
public static abstract class ProxyFactory implements MethodInterceptor {
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
public Object getProxyInstance(){
//1.
Enhancer en = new Enhancer();
//2.
en.setSuperclass(target.getClass());
//3.
en.setCallback(this);
//4. ( )
return en.create();
}
protected abstract void before(Method method);
protected abstract void after(Method method);
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
before(method);
Object returnValue = method.invoke(target, args);
after(method);
return returnValue;
}
}
//
public static class UserServiceProxy extends ProxyFactory {
public UserServiceProxy(Object target) {
super(target);
}
@Override
protected void before(Method method) {
System.out.println("before.... " + method.getName());//
}
@Override
protected void after(Method method) {
System.out.println("after.... " + method.getName());//
}
}
public static void main(String[] args) throws Exception {
UserService target = new UserServiceImpl();
UserService proxy = (UserService) new UserServiceProxy(target).getProxyInstance();
proxy.login("Stephen", "123");
}
}
3.Refs