Proxy

ローレベルからAOPを実現できる。

Java

ビジネスロジック対象

public interface Hello {

void print();

}

public class HelloImpl implements Hello {

@Override

public void print() {

// do something

}

}

Static Proxy

デメリット:interfaceにメソッドが増えたら、proxyクラスも修正必要

public class StaticProxy implements Hello {

private Hello hello;

public StaticProxy() {

this.hello = new HelloImpl(); // デフォルト

}

public StaticProxy(Hello hello) {

this.hello = hello;

}

@Override

public void print() {

//do something before

this.hello.print();

//do something after

}

private void before() {

// do something

}

private void after() {

// do something

}

}

StaticProxy proxy = new StaticProxy(new HelloImpl());

proxy.print();

JDK Dynamic Proxy

デメリット:InvocationHandlerを実装する必要がある

★方法1

public class DynamicProxy implements InvocationHandler {

private Hello hello;

public DynamicProxy() {

}

public Object bind(Hello hello) {

this.hello = hello;

return Proxy.newProxyInstance(

this.hello.getClass().getClassLoader(),

this.hello.getClass().getInterfaces(),

this);

}

@Override

public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

//do something before

Object result = method.invoke(this.hello, args);

//do something after

return result;

}

}

DynamicProxy proxy1 = new DynamicProxy();

Hello hello1a = (Hello)proxy1.bind(new HelloImpl());

hello1a.print();

★方法2

public class DynamicOtherProxy implements InvocationHandler {

private Hello hello;

public DynamicOtherProxy(Hello hello) {

this.hello = hello;

}

public Object bind() {

return Proxy.newProxyInstance(

this.hello.getClass().getClassLoader(),

this.hello.getClass().getInterfaces(),

this);

}

@Override

public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

if(args != null) {

for(Object arg : args) {

this.argValidtor((Double)arg);

}

}

//do something before

Object result = method.invoke(this.hello, args);

//do something after

return result;

}

private void argValidtor(double arg) throws Exception {

if(arg < 0) {

throw new Exception("Error");

}

}

}

DynamicOtherProxy otherProxy = new DynamicOtherProxy(new HelloImpl());

Hello hello1b = (Hello)otherProxy.bind();

hello1b.print();

※DynamicOtherProxy otherProxy = new DynamicOtherProxy(hello1a); ←Chain式もできる

//非AOP

Hello hello2 = new HelloImpl();

hello2.print();

Struts2のAOPと似ている

Struts2のActionがHelloに相当する

Struts2のInterceptorがProxyに相当する

CGLIB JDK Dynamic Proxy

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;

import net.sf.cglib.proxy.MethodInterceptor;

import net.sf.cglib.proxy.MethodProxy;

public class CglibProxyFactory implements MethodInterceptor{

private Hello hello;

// 方法1

public Object getInstance(Hello hello){

this.hello = hello;

return Enhancer.create(this.target.getClass(), this);

}

// 方法2:任意クラス

public Object getInstance(Object target){

Enhancer enhancer = new Enhancer();

enhancer.setSuperclass(this.target.getClass());

enhancer.setCallback(this);

return enhancer.create();

}

@Override

public Object intercept(Object obj, Method method,

Object[] args, MethodProxy methodProxy) throws Throwable {

// Object#toStringなどを除く

boolean objFlag = method.getDeclaringClass().getName().equals("java.lang.Object");

if(!objFlag){

//do something before

}

Object result = null;

result = methodProxy.invokeSuper(obj, args);

// result = methodProxy.invoke(obj, args);

if(!objFlag){

//do something after

}

return result;

}

}

Hello hello = (Hello)new CglibProxyFactory().getInstance(new HelloImpl());

Person person = (Person)new CglibProxyFactory().getInstance(new Person());

C#

ビジネスロジック対象

public interface IUserProcessor

{

void RegisterUser(User user);

}

public class UserProcessor : MarshalByRefObject, IUserProcessor

{

public void RegisterUser(User user)

{

Console.WriteLine("Name:{0}, Password:{1}", user.Name, user.PassWord);

}

}

※MarshalByRefObject:Remotingに向け

Static Proxy(Decorator Pattern)

public class UserProcessorDecorator : IUserProcessor

{

public IUserProcessor UserProcessor { get; set; }

public UserProcessorDecorator(IUserProcessor userProcessor)

{

this.UserProcessor = userProcessor;

}

public void RegisterUser(User user)

{

this.PreProceed(user);

this.UserProcessor.RegisterUser(user);

this.PostProceed(user);

}

private void PreProceed(User user) { ... }

private void PostProceed(User user) { ... }

}

//利用側

User user = new User { Name = "Andy", PassWord = "1234" };

IUserProcessor userProcessor = new UserProcessorDecorator(new UserProcessor());

userProcessor.RegisterUser(user);

Dynamic Proxy(.Net Remoting/RealProxy)

using System.Runtime.Remoting.Proxies;

using System.Runtime.Remoting.Messaging;

public class MyRealProxy<T> : RealProxy

{

private T _target;

public MyRealProxy(T target) : base(typeof(T))

{

this._target = target;

}

public override IMessage Invoke(IMessage msg)

{

this.PreProceede(msg);

IMethodCallMessage callMessage = msg as IMethodCallMessage;

object returnValue = callMessage.MethodBase

.Invoke(this._target, callMessage.Args);

this.PostProceede(msg);

return new ReturnMessage(

returnValue, new object[0], 0, null, callMessage);

}

private void PreProceede(IMessage msg) { ... }

private void PostProceede(IMessage msg) { ... }

}

public static class ProxyFactory

{

public static T Create<T>()

{

T instance = Activator.CreateInstance<T>();

MyRealProxy<T> realProxy = new MyRealProxy<T>(instance);

T transparentProxy = (T)realProxy.GetTransparentProxy();

return transparentProxy;

}

}

//利用側

User user = new User { Name = "Andy", PassWord = "1234" };

IUserProcessor userProcessor = ProxyFactory.Create<UserProcessor>();

userProcessor.RegisterUser(user);