首先弄个注解,给代码个入口,这个就是mongo的@EnableMongoRepositories了。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(ProxyBeanDefinitionRegistrar.class)
public @interface DefaultProxy {
String[] packages() default {};
}

还有一个注解,类似mongo的NoRepositoryBean

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface NoProxyBean { }

上面的ProxyBeanDefinitionRegistrar,就是入口了,在这里注册bean

public class ProxyBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
private ResourceLoader resourceLoader;
private Environment environment; @Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
} @Override
public void setEnvironment(Environment environment) {
this.environment = environment;
} @Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
if (annotationMetadata.getAnnotationAttributes(DefaultProxy.class.getName()) == null) {
return;
} ClasspathScannerProvider scanner = new ClasspathScannerProvider(new ArrayList<>(), registry);
scanner.setEnvironment(environment);
scanner.setResourceLoader(resourceLoader); List<BeanDefinition> beanComponentDefinitions = new ArrayList<BeanDefinition>();
for (String basePackage : getBasePackages(annotationMetadata)) {
Set<BeanDefinition> candidate = scanner.findCandidateComponents(basePackage);
beanComponentDefinitions.addAll(new ArrayList<>(candidate));
} for (BeanDefinition beanDefinition : beanComponentDefinitions) {
RootBeanDefinition bean = new RootBeanDefinition();
bean.setBeanClassName(ProxyServiceFactoryBean.class.getName());
bean.setFactoryMethodName(null);
bean.getConstructorArgumentValues().addIndexedArgumentValue(0, beanDefinition.getBeanClassName());
registry.registerBeanDefinition(beanDefinition.getBeanClassName(), bean);
}
} Set<String> getBasePackages(AnnotationMetadata metadata) {
Set<String> packages = new HashSet<>();
Map<String, Object> attr = metadata.getAnnotationAttributes(DefaultProxy.class.getName());
String[] pac = (String[]) attr.get("packages");
for (String tmp : pac) {
packages.add(tmp);
} return packages;
}
}

实现代理,是实现一个接口,在继承需要代理的类,spring-data-mongo中,这个类是SimpleMongoRepository,实现的那个接口就是自定义的实现了MongoRepository的接口(如:UserRepository)
我们也得做一个接口,所有需要代理的接口都实现它IProxyService

@NoProxyBean
public interface IProxyService { void test();
}

做一个需要被代理的类,不然没法实现代理SimpleService,就是一个最简单的类

public class SimpleService {

}

spring-data-mongo做代理的代码是MongoRepositoryFactoryBean,我们的类似的为

public class ProxyServiceFactoryBean<T extends IProxyService> implements InitializingBean, FactoryBean<T>, BeanClassLoaderAware {
private ClassLoader classLoader;
private T repository;
Class<? extends T> serviceInterface; public ProxyServiceFactoryBean(Class<? extends T> repositoryInterface) {
this.serviceInterface = repositoryInterface;
} @Override
public void afterPropertiesSet() throws Exception {
initAndReturn();
} @SuppressWarnings("unchecked")
private T initAndReturn() {
SimpleService target = new SimpleService();
ProxyFactory result = new ProxyFactory();
result.setTarget(target);
result.setInterfaces(new Class[] { serviceInterface }); result.addAdvice(new ProxyInterpreter(target, serviceInterface)); this.repository = (T) result.getProxy(classLoader);
return this.repository;
} static class ProxyInterpreter implements MethodInterceptor {
private final Object target;
private final Class<?> serviceInterface; public ProxyInterpreter(Object target, Class<?> serviceInterface) {
this.target = target;
this.serviceInterface = serviceInterface;
} public Object invoke(MethodInvocation invocation) throws Throwable { Object result = doInvoke(invocation); return result;
} private Object doInvoke(MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
Object[] arguments = invocation.getArguments(); System.out.println("invoke " + method.getName() + "(), args=" + arguments + ", target=" + target + ", interface=" + serviceInterface);
return null;
}
} public T getObject() {
return (T) initAndReturn();
}
public Class<? extends T> getObjectType() {
return serviceInterface;
}
public boolean isSingleton() {
return true;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
}

InitializingBean, FactoryBean实现这两个接口在关键点,InitializingBean是注册bean后做代理,FactoryBean是在spring处理依赖注入时,判断是不是要注入的是一个FactoryBean,如果是FactoryBean会调用getObject()来生成真正需要注入的类型。如果不实现FactoryBean,启动会报错

Description:

Field proxyService in com.fzk.proxy.test.service.ProxyController required a bean of type 'com.fzk.proxy.test.service.CustomProxyService' that could not be found.

Action:

Consider defining a bean of type 'com.fzk.proxy.test.service.CustomProxyService' in your configuration.

别忘了启动类加上注解

@DefaultProxy(packages = { "com.fzk" })

就会发现实现了IProxyService接口(并不需要实现类)可以被@Autowired,调用方法时会输出

            System.out.println("invoke " + method.getName() + "(), args=" + arguments + ", target=" + target + ", interface=" + serviceInterface);

这只是个demo,具体怎么看情况

最新文章

  1. Android 引导页公共方法LeaderPager
  2. .NET 4.0 版本号
  3. python3 jason &amp; pickle
  4. php正则表达式治疗结巴
  5. [Java Web] 1、Web开发初识——一大堆历史和技术名词
  6. Synchronized及其实现原理
  7. YTU 3004: 栈的基本运算(栈和队列)
  8. 探讨read的返回值的三种情况
  9. file_up
  10. hdoj 1342 Lotto【dfs】
  11. 有关UNICODE、ANSI字符集和相关字符串操作
  12. FusionCharts生成Flash图表常见问题FAQ
  13. (译文)React----React应用程序流式服务端渲染
  14. 调用bios喇叭发声
  15. K/3 Cloud移动BOS开发技巧 -- K/3 Cloud多数据中心时如何支持发布到云之家.
  16. java中double和float精度丢失问题及解决方法
  17. 2018.4.2 sqlite优化
  18. js: 字符集
  19. 《Visual C++开发实战1200例 第1卷》扫描版[PDF]
  20. pytorch调参经验(一)

热门文章

  1. QT creator 编辑多个UI 文件 出现 无法解析的外部符号的错误
  2. hibernate中的java对象有几种状态,其相互关系如何(区别和相互转换)。
  3. 关于JSON日期格式显示及My97日期控件
  4. 小白用advanced installer建安装包
  5. VC++Debug避免F11步进不想要的函数中
  6. Python爬虫(四)
  7. IOS开发之自定义键盘
  8. 每一行最后添加文字python脚本
  9. JPA的坑多服务主键重复
  10. 两个input在一行让它们能对齐