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