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);