前几天看公司的项目,发现一个类的注入怎么都找不到它的实现类,但是项目的注入又是成功的。
深入看了一下才发现原理:
1、tops-order-dao项目依赖jar包tops-member-client,jar包member-client-service.xml中配置pCustomerService
<bean id="pCustomerService" class="com.travelzen.tops.member.client.service.MemberThriftClientServiceProxy"
p:interface="com.travelzen.tops.member.common.iservice.CustomerService" />
2、MemberThriftClientServiceProxy实现SmartFactoryBean(继承FactoryBean)接口,Spring中如果一个类实现了FactoryBean接口,那么不会直接把这个类返还给调用着,而是返回FactoryBean::getObject的类型
在MemberThriftClientServiceProxy.getObject中采用动态代理返回CustomerServiceProxy类,在实现InvocationHandler.invoke方法中进行业务处理,这时CustomerService经过代理是可以初始化成功的。
3、InvocationHandler.invoke首先获取Thrift的MemberService.Iface,然后按照接口名称,方法,参数等调用Thrift接口
4、在Thrift的server端MemberThriftServiceImpl实现了MemberService.Iface这个接口,首先按照接口查找对应的实现类:Object svc = services.get(tReq.getDeclaredInterface()) (services是通过Spring上下文获取
MemberThriftServer.initServiceMethods)
services的初始化是采用注解:Component下的@PostConstruct
5、通过反射调用目标类
server端通过启动一个线程MemberServerStartupServlet.init-->memberThriftServer.startThreadedSelectorServer监听需要处理的方法
主要步骤是在这些,模拟一下:
1、定义一个接口:
package com.java.proxy.interfaces;
public interface IHello {
void sayHello();
}
2、定义一个接口的实现类:
package com.java.proxy.impl;
import com.java.proxy.interfaces.IHello;
public class HelloImpl implements IHello {
@Override
public void sayHello() {
System.out.println("hello java proxy!");
}
}
3、把实现类和接口放到一个容器中,也可以动态扫描,都是可以的
package com.java.proxy;
import java.util.HashMap;
import java.util.Map;
import com.java.proxy.impl.HelloImpl;
import com.java.proxy.interfaces.IHello;
public class InterfaceProxyContainer {
private static Map<String,Class<?>> containers = new HashMap<String,Class<?>>();
static{
containers.put(IHello.class.getName(), HelloImpl.class);
}
public static Map<String,Class<?>> containers(){
return containers;
}
}
4、定义参数实体类
package com.java.proxy;
public class ProxyBean {
private String interfaceName;
private String methodName;
private String paramArgs;
public String getInterfaceName() {
return interfaceName;
}
public void setInterfaceName(String interfaceName) {
this.interfaceName = interfaceName;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public String getParamArgs() {
return paramArgs;
}
public void setParamArgs(String paramArgs) {
this.paramArgs = paramArgs;
}
}
5、定义代理的目标执行类
package com.java.proxy;
import java.lang.reflect.Method;
public class InvokeProxy {
private ProxyBean proxyBean;
private Object rtValue;
public void setProxyBean(ProxyBean proxyBean) {
this.proxyBean = proxyBean;
}
public Object getRtValue() {
return rtValue;
}
public void invoke(){
Class<?> clazz = InterfaceProxyContainer.containers().get(proxyBean.getInterfaceName());
try {
Method method = clazz.getDeclaredMethod(proxyBean.getMethodName());
System.out.println(proxyBean.getParamArgs().equals("null"));
if(proxyBean.getParamArgs().equals("null"))
rtValue = method.invoke(clazz.newInstance());
else
rtValue = method.invoke(clazz.newInstance(), proxyBean.getParamArgs()).toString();
} catch (Exception e) {
e.printStackTrace();
}
}
}
6、定义代理类
package com.java.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class SimpleProxy {
private Class<?> clazz;
public void setClazz(Class<?> clazz) {
this.clazz = clazz;
}
public Object proxy() {
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class<?>[] {clazz}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
ProxyBean proxyBean = new ProxyBean();
proxyBean.setInterfaceName(clazz.getName());
proxyBean.setMethodName(method.getName());
proxyBean.setParamArgs(Arrays.toString(args));
InvokeProxy invokeProxy = new InvokeProxy();
invokeProxy.setProxyBean(proxyBean);
invokeProxy.invoke();
return invokeProxy.getRtValue();
}
});
}
}
7、测试
package com.java.proxy;
import com.java.proxy.interfaces.IHello;
public class Test {
public static void main(String[] args) {
SimpleProxy simpleProxy = new SimpleProxy();
simpleProxy.setClazz(IHello.class);
IHello ihello = (IHello) simpleProxy.proxy();
ihello.sayHello();
}
}
结果:
true
hello java proxy!
其实就是在代理类中使用反射,执行真正需要执行的类,对于返回结果,由代理类获取代理执行类的rtValue
在Spring的HttpInvoker中是否也是这样的??