[Spring] Spring 3 best practices for annotation assembly-persistent layer

Source: Internet
Author: User

Http://www.iteye.com/topic/900129

Introduction:

Many domestic applications have been using the Spring framework for a long time, and its benefits are self-evident. However, the problem is that spring2.0 and earlier versions do not yet support annotation assembly, while most enterprise applications are divided into three layers of MVC, and the configuration of bean at each layer is gradually expanding until the XML file is opened and the IDE is overwhelmed and collapsed, the situation is amazing. There is a convention over configuration software design paradigm, that is, "Convention is better than configuration", and also "convention programming ". Ruby and rails and ejb3 both follow this implementation, and spring annotations are also based on this.

 

First, before answering why to use annotation assembly, check whether the configuration file is bloated when it does not exist, such as the spring configuration file of Dao in the persistent layer.

<? XML version = "1.0" encoding = "UTF-8"?> <Beans 'omitted declarative '> <bean id = "scdbinfodao" class = "com. data. switching. DB. dao. impl. scdbinfodaoimpl "parent =" sqlmapclientdao "/> <bean id =" scftpinfodao "class =" com. data. switching. DB. dao. impl. scftpinfodaoimpl "parent =" sqlmapclientdao "/> <bean id =" scparminfodao "class =" com. data. switching. DB. dao. impl. scparminfodaoimpl "parent =" sqlmapclientdao "/> <bean id =" scparmtypedao "class =" com. data. switching. DB. dao. impl. scparmtypedaoimpl "parent =" sqlmapclientdao "/> <bean id =" scroledao "class =" com. data. switching. DB. dao. impl. scroledaoimpl "parent =" sqlmapclientdao "/> <bean id =" scrolemenudao "class =" com. data. switching. DB. dao. impl. scrolemenudaoimpl "parent =" sqlmapclientdao "/> <bean id =" scsiteloaddao "class =" com. data. switching. DB. dao. impl. scsiteloaddaoimpl "parent =" sqlmapclientdao "/> <bean id =" scsitestatdao "class =" com. data. switching. DB. dao. impl. scsitestatdaoimpl "parent =" sqlmapclientdao "/> skips the same 999 configurations ......

After use:

<?xml version="1.0" encoding="UTF-8"?><beans>    <context:annotation-config /><context:component-scan base-package="com.longtop.data.switching.db.dao"name-generator="com.seraph.bi.suite.support.core.generator.IBatisDaoBeanNameGenerator" />                        </beans>

Now everyone must understand why the annotation configuration is used. The latter is elegant between the two, and the whole is that the agreement is better than the configuration.

 

Solution:

The transformation process is to first add the @ repository tag to the DAO implementation class, which indicates that this is a service of the persistent layer. The two-layer tag @ service and @ controller are implemented as follows:

import org.springframework.stereotype.Repository;...@Repositorypublic class ScDbInfoDAOImpl extends SqlMapClientDaoSupport implements ScDbInfoDAO {...

Add the following to the configuration file:

<context:annotation-config /><context:component-scan base-package="com.longtop.data.switching.db.dao"name-generator="com.seraph.bi.suite.support.core.generator.IBatisDaoBeanNameGenerator" />

Because the interface name is scdbinfodao, and the Implementation class name is scdbinfodaoimpl, the domain name in the reference class is scdbinfodao, and the default class name generated by the container is scdbinfodaoimpl.

The beannamegenerator interface allows you to specify the name of the bean to be generated as long as it is implemented. The implementation class here is as follows:

/*** Class description: generate the spring Registration Name of the DaO of ibatis. The rule is to use the lower-case first letter and remove the suffix <br> * creation time: 12:44:20 <br> ** @ author Seraph <br> * @ Email: seraph115@gmail.com <br> */public class ibatisdaobeannamegenerator implements beannamegenerator {Private Static final logger = logger. getlogger (ibatisdaobeannamegenerator. class); Private Static final string placement = "impl"; Public String generatebeanname (beandefinition parambeandefinition, beandefinitionregistry parambeandefinitionregistry) {string [] STRs = parambeandefinition. getbeanclassname (). split ("\\. "); string shortname = STRs [STRs. length-1]; shortname = stringutils. uncapitalize (shortname); shortname = shortname. replace (dao_implements_suffix, ""); logger. debug ("generated a ibatis Dao Bean's name: [" + shortname + "]"); Return shortname ;}}

Here we can freely specify the bean name of the annotation class, But what should we do for inner class that provides datasource and sqlmapclient for Dao, that is, parent = "sqlmapclientdao?

<bean id="scRoleDAO" class="com.data.switching.db.dao.impl.ScRoleDAOImpl"        parent="sqlMapClientDAO" />
<bean id="sqlMapClientDAO"    class="org.springframework.orm.ibatis.support.SqlMapClientDaoSupport"    abstract="true">    <property name="dataSource" ref="${jdbc.dataSource}" />    <property name="sqlMapClient" ref="sqlMapClient" /></bean><bean id="sqlMapClient" class="com.seraph.bi.suite.support.core.IncludesSqlMapClientFactoryBean">    <property name="configLocation" value="classpath:ibatis/platform/orcl/sqlmap.xml" /></bean>

To solve this problem, we implemented a post-injection class: sqlmapclientdaoinjector, which is used to inject dependencies after Dao is loaded into the context. The class code is as follows:

/*** Class description: inject dependencies into the DAO of ibatis <br> * Creation Time: 10:51:28 <br> ** @ author Seraph <br> * @ Email: seraph115@gmail.com <br> */public class sqlmapclientdaoinjector implements applicationcontextaware, initializingbean {Private Static final logger = logger. getlogger (sqlmapclientdaoinjector. class); @ override public void setapplicationcontext (applicationcontext) throws beansexception {springcontext. setapplicationcontext (applicationcontext);} public void afterpropertiesset () throws exception {assert. notnull (datasource, "Property 'datasource 'is required. "); assert. notnull (sqlmapclient, "Property 'sqlmapclient' is required. "); injectdependence ();} private void injectdependence () {// get context applicationcontext CTX = springcontext. getapplicationcontext (); // obtain the Map <string, sqlmapclientdaosupport> map = CTX in the context by type. getbeansoftype (Org. springframework. orm. ibatis. support. sqlmapclientdaosupport. class, true, true); For (iterator <string> I = map. keyset (). iterator (); I. hasnext ();) {try {string supportname = (string) I. next (); sqlmapclientdaosupport support = map. get (supportname); // post-injection dependent support. setsqlmapclient (sqlmapclient); support. setdatasource (datasource);} catch (runtimeexception e) {logger. error ("sqlmapclientdaoinjector. injectdependence () ", e) ;}} public void setdatasource (datasource) {This. datasource = datasource;} public void setsqlmapclient (sqlmapclient) {This. sqlmapclient = sqlmapclient;} private datasource; private sqlmapclient ;}

Then add the configuration of this class,

    <bean id="sqlMapClientDaoInjector"        class="com.seraph.bi.suite.support.dao.assembly.SqlMapClientDaoInjector">        <property name="dataSource" ref="${jdbc.dataSource}" />        <property name="sqlMapClient" ref="sqlMapClient" />    </bean>

To sum up the Implementation ideas, first add the @ repository annotation label to the class to be automatically loaded. For the conventions that need to change the default class name generation rules, write the classes that implement the beannamegenerator interface, then, the built-in class configurations that need to be abstracted are dependent on the implementation of injection after self-implementation. For this example, we need to understand the implementation idea, that is, to understand the working principle and design idea of spring containers, and then we can implement beneficial and necessary improvements for them, but ultimately they are designed to simplify the configuration, less unnecessary workload.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.