纯粹作为个人记录,不喜勿喷。
如有解释不对的地方,这其中并没有误人子弟的意思,恳请指正。
整体思路
问题:
1:接口是不能被实例化的。
2:在没有具体实例类下,如何通过接口做到像实例类一样的方式调用方法。
3:要如何通过spring的方式生成具体的bean。
解决:
1:实现BeanDefinitionRegistryPostProcessor,ResourceLoaderAware,ApplicationContextAware的三个spring的接口。
2:扫描特定的类路径的包
3:实现FactoryBean接口,配合sping的启动,java动态代理就是在这儿的getObject()方法中完成。
4:修改beanDefinition的beanClass为代理工厂bean。
5:手动生成代理接口的beanDefinitionHolder注册到beanFactory内,以便spring实现自动创建bean。
代码:
生成beanDefinitionHolder
code
@Component
public class TestBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor, ResourceLoaderAware, ApplicationContextAware {
private ApplicationContext applicationContext;
private ResourceLoader resourceLoader;
private String packagePath;
private MetadataReaderFactory metadataReaderFactory;
private ResourcePatternResolver resourcePatternResolver;
private Environment environment;
private BeanNameGenerator beanNameGenerator;
private ScopeMetadataResolver scopeMetadataResolver;
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
Set<BeanDefinition> beanDefinitions = scannerPackages();
for (BeanDefinition beanDefinition : beanDefinitions) {
GenericBeanDefinition definition = (GenericBeanDefinition) beanDefinition;
// 获取beanName
String beanName = this.beanNameGenerator.generateBeanName(beanDefinition, registry);
// 设置FactoryBean属性
definition.getPropertyValues().add("rpcInterface", beanDefinition.getBeanClassName());
// 把beanClass修改为工程
definition.setBeanClass(ServiceFactory.class);
// beanHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(definition, beanName);
// 注册
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
// 环境变量
this.environment = applicationContext.getEnvironment();
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
// 解析类元数据
this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
// 针对类批量扫描包解析,但是需要对占位符进行处理
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
this.beanNameGenerator = new AnnotationBeanNameGenerator();
this.scopeMetadataResolver = new AnnotationScopeMetadataResolver();
}
// 解析包下的类
private Set<BeanDefinition> scannerPackages() {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
String classPath = "classpath*:" + resolveBasePackage() + "/**/*.class";
Resource[] resources = this.resourcePatternResolver.getResources(classPath);
for (Resource resource : resources) {
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
// 设置scope属性值
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(sbd);
sbd.setScope(scopeMetadata.getScopeName());
sbd.setResource(resource);
sbd.setSource(resource);
candidates.add(sbd);
}
} catch (Exception e) {
}
return candidates;
}
// 解析占位符,并且把 "." 改成 "/"
private String resolveBasePackage() {
return ClassUtils.convertClassNameToResourcePath(this.environment.resolveRequiredPlaceholders(packagePath));
}
public void setPackagePath(String packagePath) {
this.packagePath = packagePath;
}
}
TestBeanDefinitionRegistr实现了BeanDefinitionRegistryPostProcessor, ResourceLoaderAware, ApplicationContextAware这3个接口,目的是获得spring的ApplicationContext,ResourceLoader以及在spring启动的过程中,会自动调用postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法,以便我们可以对spring的BeanDefinition做个性化的处理。 目前我们的类资源加载,动态生成BeanDefinition都是在这个地方作为入口处理。
实现代理的FactoryBean
code
public class ServiceFactory implements FactoryBean {
private Class<T> rpcInterface;
@Override
public T getObject() throws Exception {
return (T) Proxy.newProxyInstance(this.rpcInterface.getClassLoader(), new Class[]{this.rpcInterface}, new MyInvocationHandler());
}
@Override
public Class<?> getObjectType() {
return rpcInterface;
}
@Override
public boolean isSingleton() {
return true;
}
public void setRpcInterface(Class<T> rpcInterface) {
this.rpcInterface = rpcInterface;
}
class MyInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我是代理类");
return "result test";
}
}
}
ServiceFactory 就是我们的工厂Bean,代理类的生成就是在这个地方实现的。 主要是使用了java JDK动态代理。
代理的接口
public interface BookService {
void book();
}
启动类
code
public class Test { public static void main (String[] args) {
try {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/common/server.xml");
BookService service = context.getBean("bookService", BookService.class);
service.book();
} catch (Exception e) {
System.out.println(e);
}
}
}
server.xml的配置
code
<bean id="testBeanDefinitionRegistry" class="com.demo.service.mybatisDemo.TestBeanDefinitionRegistry">
<property name="packagePath" value="com.demo.service.mybatisDemo.interfaces"></property>
</bean>
结果展示

用途
在代理类invoke的地方其实也可以用来实现简单的RPC,作为netty的client端。