Wednesday, January 15, 2014

Spring Course: V24-V32 Wiring with Annotations

V24 Adding Support for Annotation-Based Wiring
in order to be able to use use annotations for wiring you should add the follwoing to beans.xml
1- context namespace
2- <context:annotation-config> tag

<beans xmlns:context="http://www.springframework.org/schema/context" >
<context:annotation-config></context:annotation-config>
.....
</beans>

V25 The "Autowired" Annotation 
after we added the context namespace (in V24), now you define your beans in beans.xml as we normally do 

<bean id="logger" class="Logger"></bean>
<bean id="consoleWriter" class="ConsoleWriter"></bean>
<bean id="fileWriter" class="FileWriter"></bean>

now you can do the wiring by using @Autowired, you can use @Autowired with constructor, setMethod and properties

public class Logger {
        //wiring properties
@Autowired 
private ConsoleWriter consoleWriter;
        private FileWriter fileWriter;

        //wiring constructor 
        @Autowired
public Logger(ConsoleWriter consoleWriter, FileWriter fileWriter) {
this.consoleWriter = consoleWriter;
this.fileWriter = fileWriter;
}

         //wiring set method
        @Autowired
public void setConsoleWriter(ConsoleWriter writer) {
this.consoleWriter = writer;
}
........
}

V26 Optional Beans
lets say that you have this class 
public class Logger {       
        private FileWriter fileWriter;
      
        @Autowired
public Logger(FileWriter fileWriter) {
this.fileWriter = fileWriter;
}
}

this class needs a FileWriter bean, and we dont have any FileWriter bean in beans.xml
if you run the program you will get an exception because Spring cannot find a FileWriter bean to wire.

you can fix that by writing @Autowired(required=false) this will tell spring that even if you cannot find the required bean continue and consider the value as null
no you should be careful as the fileWriter value is null, so you should write something like
if (fileWriter != null) {doSomething()};

V27 Using Qualifiers
lets say we have this class 
public class Logger {       
        private ConsoleWriter consoleWriter;
        
        @Autowired
public void setConsoleWriter(ConsoleWriter writer) {
this.consoleWriter = writer;
}
}

and in beans.xml we have 2 FileWriter beans
<bean id="consoleWriter" class="ConsoleWriter"></bean>
<bean id="squirrel" class="ConsoleWriter"></bean>

so now we have an ambiguity and spring will throw exception, to fix this issue you can use Qualifier.

1- you add a qualifier tag to the bean 
2- you use @Qualifier

in beans.xml 
<bean id="consoleWriter" class="ConsoleWriter"> <qualifier value="toconsole"></qualifier></bean>
<bean id="squirrel" class="ConsoleWriter"></bean>
       
and in Logger class

        @Autowired
@Qualifier("toconsole")
public void setConsoleWriter(ConsoleWriter writer) {
this.consoleWriter = writer;
}

so by that i am telling Spring to wire the bean with a qualifier tag "toconsole"

another scenario is if you have super class ambiguaity like this:
public class ConsoleWriter implements LogWriter {...}
public class FileWriter implements LogWriter {...}
public class Logger {
      private LogWriter writer;

        @Autowired
public Logger(LogWriter writer) {
this.writer= writer;
}
}

as you can see we have ConsoleWriter and FileWriter implement LogWriter, and Logger has a LogWriter property.

now in beans.xml we have
<bean id="consoleWriter" class="ConsoleWriter"></bean>
<bean id="fileWriter" class="FileWriter"></bean>

Spring will throw an exception because of the ambiguty, it cannot decide which beans to wire.

to fix this issue you can use @Qualifier in the required class and in Logger class like this

@Qualifier("filewriter")
public class FileWriter implements LogWriter {...}

public class Logger {
      private LogWriter writer;

        @Autowired
        @Qualifier("filewriter")
public Logger(LogWriter writer) {
this.writer= writer;
}
}

so we marked the class as filewriter, and we used it in the Logger.

V28 The Resource Annotation
we used @Autowired in the previous videos, there is another way to do wiring which is @Resource and to solve ambiguity when you use @Resource you write @Resource(name="TheIDofTheBean"

public class Logger {
      private LogWriter writer;
       @Resource(name="filewriter")
public Logger(LogWriter writer) {
this.writer= writer;
}
}
<bean id="fileWriter" class="FileWriter"></bean>

V29 Init and Destroy Methods
we saw before how to define Init and Destroy methods in beans.xml, you can use @PostConstruct & @PreDestroy to define by taging 

V30 The Inject Annotation
in previous videos we talked about @Autowire and @Resource for wiring, there is another way which is @Inject to solve ambiguity with @Inject you should use @Name(value="ID")

public class Logger {
      private LogWriter writer;
       @Inject
       @Name(value="fileWriter")
public Logger(LogWriter writer) {
this.writer= writer;
}
}
<bean id="fileWriter" class="FileWriter"></bean>

V31 Automatic Beans Discovery
currently we are defining beans in beans.xml, you can use annotation to define beans, in order to do that 
1- you need the context interface
2- use <context:component-scan>
3- use @Component

<beans xmlns:context="http://www.springframework.org/schema/context" >
<context:annotation-config></context:annotation-config>
<context:component-scan base-package="com.caveofprogramming.spring.test"></context:component-scan>

as you can see in component-scan we define the package that Spring should scan in order to find the beans

now you writ:
@Component
public class Logger {...}

now Logger is a bean, and sure you can write @Component("SOMEID") which give an id to the component.

V32 Setting Property Value
you can inject property value like this 
@Inject
public void setID(@Value("10") int id) {...}


No comments:

Post a Comment