本文实现扫描对应包下接口,使用JDK动态代理进行接口代理
一丶JDK动态代理的接口
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DemoRegistry {
}
@DemoRegistry
public interface DemoBean {
String hello();
}
public class DemoInvocationHandler implements InvocationHandler {
public static Object build(Class> type) {
// 创建代理对象,参数分别为类加载器,需要的接口Class对应(因为代理的type就是接口,所以直接new一个class数组就行),具体的代理实现
return Proxy.newProxyInstance(type.getClassLoader(), new Class[]{type}, new DemoInvocationHandler());
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 自己实现对应的代理逻辑
// 这里实现为如果方法定义的class为Object,就直接调用这个对象的方法
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
// 方法返回值为String,就返回一个hell word,代理的具体逻辑可以自己实现
Class> returnType = method.getReturnType();
if (returnType == String.class) {
return "hell word";
}
return null;
}
}
public class DemoFactoryBean implements FactoryBean {
public final Class type;
public DemoFactoryBean(Class type) {
this.type = type;
}
@Override
public T getObject() throws Exception {
// 获取代理对象,使用JDK动态代理
return (T) DemoInvocationHandler.build(type);
}
@Override
public Class getObjectType() {
// 获取对象的类型
return type;
}
}
二丶接口扫描及注册BeanDefinition
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
// @import注解是Spring提供的导入对应的类的注解,通过导入具体实现了importBeanDefinitionRegistrar接口的类可以自己注册BeanDefinition
@import({DemoRegistrarTest.class})
public @interface EnableDemo {
String[] value();
}
public class DemoRegistrarTest implements importBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry) {
// 获取类上的EnableDemo注解的属性
Map map = importingClassmetadata.getAnnotationAttributes(EnableDemo.class.getName());
// 类扫描器
MyClassScan scan = new MyClassScan(registry);
// 从注解配置中获取扫描的包路径进行扫描
int scanCount = scan.scan((String[]) map.get("value"));
System.out.println(scanCount);
}
}
public class MyClassScan extends ClassPathBeanDefinitionScanner {
public MyClassScan(BeanDefinitionRegistry registry) {
super(registry, false);
// 注册筛选器
registerFilters();
}
public void registerFilters() {
// 筛选只有包含DemoRegistry注解的接口
addIncludeFilter(new AnnotationTypeFilter(DemoRegistry.class));
}
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
// 是不是接口且是独立的bean(不依赖其他bean)
return beanDefinition.getmetadata().isInterface() && beanDefinition.getmetadata().isIndependent();
}
@Override
public Set doScan(String... basePackages) {
// 进行扫描,获取BeanDefinitionHolder
Set beanDefinitionHolders = super.doScan(basePackages);
// 循环替换beanDefinition中的beanClass为FactoryBean,不进行替换的话,beanClass是接口,Spring无法通过接口得到Bean对象
for (BeanDefinitionHolder definitionHolder : beanDefinitionHolders) {
// 获取beanDefinition
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) definitionHolder.getBeanDefinition();
// 获取扫描出的接口的beanClassName
String beanClassName = beanDefinition.getBeanClassName();
// 设置BeanClass为DemoFactoryBean
beanDefinition.setBeanClass(DemoFactoryBean.class);
// 添加构造方法的参数,DemoFactoryBean的构造方法需要Class对象,这里设置的是string的参数,spring会使用Class.forName加载
// 成DemoFactoryBean中构造方法需要的类参数
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);
}
return beanDefinitionHolders;
}
}
三丶测试
@Service
public class DemoInterfaceTest {
@Autowired
private DemoBean demoBean;
@PostConstruct
public void init() {
// 执行方法,这里就会执行代理中的逻辑
System.out.println(demoBean.hello());
System.out.println(demoBean.toString());
// 输出
// hell word
// com.example.cachedemo.factory.DemoInvocationHandler@30bf26df()
}
}



