spring动态添加bean


不知道大家想过没有,我们使用mybatis的时候只要写接口和配置上一个sql语句就可以了,单从代码的角度来看,这是不合理的。

所以我们通常在service里面注入的mapper它其实是一个代理对象

回到本人上一篇博客spring给容器中注入组件的几种方式

1.包扫描+组件注解标签注解

这种方式一般适用于自己写的类,动态代理的类无法添加(就算你自己动态生成的类上有注解标签,spring也无法扫描)

2.@bean

这种方式适用于加入第三方库中的类

这种方式真的可以吗?仔细想想,这种方式只能一个一个添加,像mybatis有这么多的mapper我们一个一个的加就麻烦了

3.@improt

这种方式的简单用法是肯定不行的,因为是动态生成的类,你无法再类写@improt(xxxx.class)

4.使用spring提供的factoryBean

写一个类实现factoryBean接口,重写getObject方法

这种方式显然和@bean有一样的缺陷,返回值只能有一个,还是要一个一个添加

======================================主文来了=======================================

解决办法就是@improt>>>>实现ImportBeanDefinitionRegistrar接口+.使用spring提供的factoryBean

public class MyMapperFactoryBean implements FactoryBean{ @Autowired private SqlSessionFactoryBean sqlSessionFactoryBean; private Class aClass; public void setaClass(Class aClass) { this.aClass = aClass; } public MyMapperFactoryBean(Class aClass) { this.aClass = aClass; } //产生动态代理,需要产生代理的类型在构造方法传入 @Nullable @Override public Object getObject() throws Exception { Class[] clazz=new Class[]{aClass}; Object obj = Proxy.newProxyInstance(this.getClass().getClassLoader(), clazz, new MapperInvocationHandler(sqlSessionFactoryBean)); return obj; } @Nullable @Override public Class<?> getObjectType() { return TestMapper.class; } }

 

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{ @Override public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) { //注册MyMapperFactoryBean //为什么不用其他方式注册MyMapperFactoryBean呢 因为这里是代码形式,可以循环,产生多个 BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(MyMapperFactoryBean.class); AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition(); //传入MyMapperFactoryBean的构造方法类型 你要代理那个类就传入那个类 beanDefinition.getConstructorArgumentValues().addGenericArgumentValue("com.tjx.mapper.TestMapper"); //注册 beanDefinitionRegistry.registerBeanDefinition("mapper",beanDefinition); } }

=============================这样就OK了,讲讲思路==================================

1.循环注册

 

2.FactoryBean这个类被我们注册到了容器中,所有可以使用spring容器中的组件  如sqlsessionFactoryBean

    //这里因为我们没有使用mybatis为我们生成动态代理 所以这里不能使用mybatis的功能 //但是mybatis官方他自己把sqlSessionFactoryBean传入进来就是能用的 (这里有点绕,因为我不可能去把mybatis的底层实现自己写一遍) @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String str=method.getAnnotation(Select.class).value()[0]; //获取方法注解上的sql语句 System.out.println("查询数据库"+str); List<Test> lists=new ArrayList<>(); Connection con=null; PreparedStatement ps=null; ResultSet rs=null; int count=0; try { con=DBHelper.getCon(); ps=con.prepareStatement(str); rs=ps.executeQuery(); while (rs.next()){ Test test=new Test(); int id = rs.getInt("id"); String name = rs.getString("name"); test.setId(id); test.setName(name); lists.add(test); } } catch (Exception e) { e.printStackTrace(); } finally{ DBHelper.myClose(con, ps, rs); } // SqlSessionFactory object = sqlSessionFactoryBean.getObject(); // SqlSession sqlSession = object.openSession(); // System.out.println(sqlSession); // List<Test> objects = sqlSession.selectList(str); return lists; }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM