Wiring up Spring framework Dependency Injection with annotations
Q13. How will you go about wire components using Spring annotations?
A13. Here are the high level steps involved in wiring up a web application in Spring using annotations.
web.xml --> myAppServletContext.xml --> myapp-applicationContext.xml --> MyAppController.java --> MyAppService.Java --> MyAppDaoImpl.java
Pay attention to how the different artifacts are wired up using both Spring xml files and annotations. The Spring beans can be wired either by name or type. @Autowired by default is a type driven injection. @Autowired is Spring annotation, while @Inject is a JSR-330 annotation. @Inject is equivalent to @Autowired or @Autowired(required=true). @Qualifier spring annotation can be used to further fine-tune auto-wiring. There may be a situation when you create more than one bean of the same type and want to wire only one of them with a property, in such case you can use @Qualifier annotation along with @Autowired to remove the confusion by specifying which exact bean will be wired.
The Step 3: demonstrates "name" driven wiring up using annotations.
Step 1: The web.xml file snippet.
<servlet> <servlet-name>myAppServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/META-INF/spring/myAppServletContext.xml</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <!-- Creates the Spring Container shared by all Servlets and Filters --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <-- add resolvers here, if required--> <servlet-mapping> <servlet-name>myAppServlet</servlet-name> <url-pattern>/myapp/*</url-pattern> </servlet-mapping>
Step 2: The myAppServletContext.xml file snippet.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xmlns:batch="http://www.springframework.org/schema/batch" xmlns:cm="http://camel.apache.org/schema/spring" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd"> <!-- import context files as it is not a best practice to define everything in one xml file--> <import resource="classpath:/META-INF/spring/myapp-applicationContext.xml" /> <!-- scan for any Java based wiring up classes with @Configuration & @Bean annotations --> <context:component-scan base-package="com.myapp.camel.config" /> <!-- exposing beans via JMX not important for this tutorial --> <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false"> <property name="autodetect" value="true"></property> <property name="namingStrategy" ref="namingStrategy"></property> <property name="assembler" ref="assembler"></property> </bean> <bean id="attributeSource" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource" /> <bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler"> <property name="attributeSource" ref="attributeSource" /> </bean> <bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy"> <property name="attributeSource" ref="attributeSource" /> </bean> </beans>
Step 3: The myapp-applicationContext.xml snippet with config to enable auto-scan with annotations.
As you can see, the controller, service, and DAO layer classes not configured here as they are scanned via annotation (i,e @Component is the parent annotation from which the other annotations like @Service, @Resource, @Repository etc are defined)
The annotations shown above allow you to declare beans that are to be picked up by autoscanning with <context:component-scan/> or @ComponentScan.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xmlns:security="http://www.springframework.org/schema/security" xmlns:batch="http://www.springframework.org/schema/batch" xmlns:task="http://www.springframework.org/schema/task" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd"> <mvc:annotation-driven /> <context:annotation-config /> <!-- load properties files --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="ignoreUnresolvablePlaceholders" value="true"/> <property name="location" value="classpath:/myapp/myapp.properties"/> <property name="placeholderPrefix" value="$myapp{"/> <property name="placeholderSuffix" value="}"/> </bean> <!-- any packages to exclude for component scanning--> <context:component-scan base-package="com.myapp"> <context:exclude-filter type="regex" expression="com.myapp.camel.config.MyAppCamelConfig"/> </context:component-scan> <!-- comment this line locally to bypass security access control in development. But don't check this in commented as security will be turned off --> <!-- Spring security--> <security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled" jsr250-annotations="enabled"/> </beans>
Step 4: The controller class that handles HTTP requests. Annotations are used to wire up dependencies.
@Controller public class MyAppController { private final MDCLoggingHelper MDCLoggingHelper = new MDCLoggingHelper(); @Resource(name = "myapp_Service") private MyAppService myAppService; @RequestMapping( value = "/portfolio/{portfoliocd}/summaries", method = RequestMethod.GET, produces = "application/json") @ResponseBody public PortfolioSummaryVO retrievePortfolioSummary( @PathVariable(value = "portfoliocd") String portfolioCode, @RequestParam(value = "valuationDate", required = true) @DateTimeFormat(pattern = "yyyyMMdd") Date valuationDate HttpServletResponse response) throws Exception { //.................. } }
Step 5: The service class that handles business logic in a protocol agnostic manner. Annotations are used to wire up dependencies.
@Service(value = "myapp_Service") @Transactional(propagation = Propagation.SUPPORTS) public class CashForecastServiceImpl implements CashForecastService { @Resource(name = "myapp_Dao") private MyAppDao myAppDao; @Value("$cf{myapp.file_delimiter}") private String defaultFeedDelimiter; //read from myapp.properties files @Override public PortfolioSummaryVO retrievePortfolioSummaries(MyAppPortfolioCriteria criteria, FeedFileMetaInfo feedFileMeta) { //.............. } }
Step 6: The DAO class that makes database calls via a JDBC template. The configuration of JDBC template is not shown.
@Repository(value = "myapp_Dao") public class CashForecastDaoImpl implements CashForecastDao { @Resource(name = "myapp_JdbcTemplate") private JdbcTemplate jdbcTemplateSybase;//configure via jdbcContext.xml public PortfolioSummaryVO retrievePortfolioSummaries(MyAppPortfolioCriteria criteria) { //............ } }
The @Configuration annotation was designed as the replacement for XML configuration files. The @Configuration annotated classes can still able to use annotated(@Autowired, @Inject etc.) fields and properties to request beans (and even other @Configuration annotated beans too) from the container. Here is an example of how Apache Camel is wired up using the @configuration and @bean annotations in Step 2.
Labels: Spring
0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home