4

动态代理接口并注册到spring容器

 2 years ago
source link: https://wakzz.cn/2017/12/26/java/%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E6%8E%A5%E5%8F%A3%E5%B9%B6%E6%B3%A8%E5%86%8C%E5%88%B0spring%E5%AE%B9%E5%99%A8/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

实现将一个接口动态代理,并将该代理对象在spring容器初始化完成前注册到spring容器中。实现可以通过@Autowired等注释或其他方法从spring容器中获取该代理对象。

2、灵感来源

翻mybatis的源代码获得,

源代码下载

3.1、接口类

public interface TestService {

public String sayHello();
}

3.2、代理类

public class MyProxy implements InvocationHandler{

private Class<?> interfaceClass;

public Object bind(Class<?> cls) {
this.interfaceClass = cls;
return Proxy.newProxyInstance(cls.getClassLoader(), new Class[] {interfaceClass}, this);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return "hello world";
}

}

3.3、代理工厂

public class MyProxyFactory<T> implements FactoryBean<T> {

private Class<T> interfaceClass;
public Class<T> getInterfaceClass() {
return interfaceClass;
}
public void setInterfaceClass(Class<T> interfaceClass) {
this.interfaceClass = interfaceClass;
}
@Override
public T getObject() throws Exception {
return (T) new MyProxy().bind(interfaceClass);
}

@Override
public Class<?> getObjectType() {
return interfaceClass;
}

@Override
public boolean isSingleton() {
// 单例模式
return true;
}

}

3.4、注册spring容器

@Component
public class MyRegistryBean implements ApplicationContextAware,BeanDefinitionRegistryPostProcessor{

private ApplicationContext ctx;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
// 需要被代理的接口
Class<?> cls = TestService.class;
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(cls);
GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
definition.getPropertyValues().add("interfaceClass", definition.getBeanClassName());
definition.setBeanClass(MyProxyFactory.class);
definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
// 注册bean名,一般为类名首字母小写
beanDefinitionRegistry.registerBeanDefinition("testService", definition);
}
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
this.ctx = ctx;
}

}

3.5、测试

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration({"classpath*:applicationContext.xml"})
public class Start {

@Autowired
TestService testService;

@Test
public void test() {
System.out.println(testService.sayHello());
}
}

控制台成功输出“hello world”,即成功在spring容器初始化完成前,将TestService接口代理,并将代理类注册到spring容器中。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK