How spring-ioc turns an interface into springbean

interface-->proxy object-->springbean

The first thing to determine is to turn an interface into an object. JDK dynamic proxy is perfect, but what should I do to hand the proxy object to spring management?

What are the ways for us to hand over an object to spring for management?

BeanFactory, FactoryBean, ImportSelector, factory method (xml configuration factory-method="createObject")

I have introduced BeanFactory, FactoryBean

Now let’s talk about ImportSelector

//1扫描
@Configuration
@ComponentScan("org.springframework.spring.mybatis.*")
@TestScanMapper
@Import(TestImportSelector.class)//添加注解
public class AppConfig {
}

//2Java object
public class TestBo {
}

//3 自定义实现ImportSelector接口
public class TestImportSelector implements ImportSelector {
	@Override
	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		return new String[]{TestBo.class.getName()};
	}
}

//4测试
public class MainDemo {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
		System.out.println(ac.getBean(TestBo.class));
	}

控制台打印结果
org.springframework.spring.mybatis.TestBo@5abca1e0

 

Implementing this interface can turn a Java object into a springbean

But the name of the class name is needed, and the proxy object class name is not fixed ($Proxy0,0 will change)

Spring provides such an interface ImportBeanDefinitionRegistrar, we combine the FactoryBean interface to see the code implementation

We first define an interface

//接口
public interface TestMapper {

//如果使用@MapperScan("org.springframework.spring.mybatis.*")注解请将getAll改成默认的list
	@Select("select * from user where 1=1 and id=#{param}")
	List<Map<Integer,String>> getAll(@Param("param") String param);
}

//实现FactoryBean接口 和 InvocationHandler接口
public class TestFactoryBean implements FactoryBean, InvocationHandler {

	Class clazz;
	public TestFactoryBean(Class clazz){//构造方法创建对象
		this.clazz = clazz;
	}

	@Override//此处为获取代理方法的注解值,如:@Select("select * from user where uid=#{param}")打印sql。。。。。
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Class<?>[] parameterTypes = method.getParameterTypes();
		for (int i = 0; i < parameterTypes.length; i++) {
			Method method1 = proxy.getClass().getInterfaces()[0]
					.getMethod(method.getName(), parameterTypes[0]);
			Select select = method1.getDeclaredAnnotation(Select.class);
			System.out.println(select.value()[0]);
		}
		return null;
	}

	@Override
	public Object getObject() throws Exception {
		Class[] clazzs = new Class[]{clazz};
		Object proxy = Proxy.newProxyInstance(this.getClass().getClassLoader(), clazzs, this);
		return proxy;
	}

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

 

Let's first look at the rewritten getObject() method, which directly returns the proxy object, but we can no longer implement the ImportSelector interface, as mentioned above

public class TestImportBeanDifinitionRegistrar implements ImportBeanDefinitionRegistrar {
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

//扫描TestMapper这个接口,此处为模拟固定
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(TestMapper.class);
//得到一个beanDefinition
		GenericBeanDefinition beanDefinition =(GenericBeanDefinition) builder.getBeanDefinition();
        //设置beanclass
		beanDefinition.setBeanClass(TestFactoryBean.class);
//通过构造方法新建对象
	beanDefinition.getConstructorArgumentValues().addGenericArgumentValue("org.springframework.spring.mybatis.mapper.TestMapper");
//注册
		registry.registerBeanDefinition("testMapper",beanDefinition);
	}
}

Use annotations to enable spring's implementation of this interface

@Retention(RetentionPolicy.RUNTIME)
@Import(TestImportBeanDifinitionRegistrar.class)
public @interface TestScanMapper {
}

Finally, you can directly use the main method to test to remove the beanName from the container as the testMapper singleton object

Finish.

Guess you like

Origin blog.csdn.net/qq_38108719/article/details/100539913