Good day!
I set myself a goal to learn the Spring framework for Java. During the study, I decided to check on myself the learning algorithm of Richard Feynman: organize-simplify-train another. In general, I began to record a series of short lessons for beginners on working in Spring. For those who want to repeat laid out the
source code .
Lesson 01. Understanding IoC
So, we will gather together poets, let them compose and read us their poems.
First, let's declare an interface that generates verses
src \ main \ java \ spring \ interfaces \ Lyricist.java:')
package spring.intarfaces; public interface Lyricist { public String Generate(); }
We implement this interface in the
src \ main \ java \ spring \ impls \ Mayakovsky.java class :
package spring.impls; import spring.intarfaces.Lyricist; public class Mayakovsky implements Lyricist { @Override public String Generate() { return " \r\n" + " \r\n" + " \r\n" + " ?"; } }
Let's prescribe that we will create a specific Mayakovsky object in the
src \ main \ resources \ ApplicationContext.xml xml file:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="LyricistBean1" class="spring.impls.Mayakovsky"/> </beans>
Associated id LyricistBean1 with the name of the class Mayakovsky. Almost everything is ready, all that is missing is the calling class
src \ main \ java \ spring \ main \ Start.java :
package spring.main; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import spring.intarfaces.Lyricist; public class Start { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); Lyricist lyr1 = context.getBean("LyricistBean1", Lyricist.class); System.out.println(lyr1.Generate()); ((ConfigurableApplicationContext) context).close();
In the Start class, we read our configuration file, created an instance of the poet named Bean LyricistBean1. Received a copy of the poet Mayakovsky. The Generate () function has returned immortal strings to us:
And you
nocturne play
we could
flute downpipes?
Lesson 02. Selecting the created instance through the configuration file.
Suppose a friend helped us and provided another implementation of our interface Lyricist
src \ main \ java \ spring \ impls \ Poushkin.java :
package spring.impls; import spring.intarfaces.Lyricist; public class Poushkin implements Lyricist { @Override public String Generate() { return " :\r\n" + " ,\r\n" + " ,\r\n" + " ."; } }
Let's change the Mayakovsky word to the Poushkin word in the ApplicationContext.xml configuration file.
Run the program. We
get a completely different result
without rebuilding :
I remember a wonderful moment
Before me was you
Like fleeting vision,
Like a genius of pure beauty.
Lesson 03. Beans in code, not in configuration file
Suppose we do not like to give the choice of the created class of the poet
into the hands of fate in the configuration file.
Change the class Poushkin.java
- Add import library import org.springframework.stereotype.Component;
- Set the Component annotation ("LyricistBean1") before class declaration
Thus, we hinted to Spring that we want to see Poushkin as the first poet, and not anybody else.
It remains a bit to fix the configuration file ApplicationContext.xml:
1. Add the context namespace above: xmlns: context = "
www.springframework.org/schema/context ";
2. Delete the unnecessary line: />
3. Add instead a command to automatically add to the program beans from all classes located in the spring.impls directory:
<context: component-scan base-package = "spring.impls" />
As a result, the ApplicationContext.xml file should look like this:
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> <context:component-scan base-package="spring.impls"/> </beans>
We start. We get the same result as in the previous lesson.
Lesson 04. Configuration Class
Let's get rid of the xml file completely.
All settings can be in the java-class. Sometimes it is convenient.
Add a special configuration class
src \ main \ java \ spring \ main \ LyricistConfiguration.java to our program:
package spring.main; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @ComponentScan(basePackages = { "spring.impls" }) @Configuration public class LyricistConfiguration { }
@ComponentScan shows in which directory to search for bins.
@Configuration reports that our class is special, configuration.
All xml-file is no longer needed. It remains to report this news to our main class:
- Let's add it with the necessary import import org.springframework.context.annotation.AnnotationConfigApplicationContext;
- Replace the context creation string
ApplicationContext context = AnnotationConfigApplicationContext (LyricistConfiguration.class);
As a result, the main
src \ main \ java \ spring \ main \ Start.java file should look like this:
package spring.main; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import spring.intarfaces.Lyricist; public class Start { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(LyricistConfiguration.class); Lyricist lyr1 = context.getBean("LyricistBean1", Lyricist.class); System.out.println(lyr1.Generate()); ((ConfigurableApplicationContext) context).close();
Everything starts and still produces the immortal Pushkin lines. Everything is working. But already without xml.
Lesson 05. Singleton and Prototype
Explore the possibilities of the configuration file. Therefore, let us go back to the project from the second lesson. Let's try to create two instances of the Poushkin class in Start.java and make sure that the great poet is the same:
Lyricist lyr1 = context.getBean("LyricistBean1", Lyricist.class); System.out.println(lyr1.Generate()); System.out.println(lyr1.hashCode()); Lyricist lyr2 = context.getBean("LyricistBean1", Lyricist.class); System.out.println(lyr2.Generate()); System.out.println(lyr2.hashCode());
And the poems are the same, and the hash code is sorted. Everything is good.
Add to our project a simple citizen who does not write verses
src \ main \ java \ spring \ impls \ SimpleMan.java :
package spring.impls; import spring.intarfaces.Lyricist; public class SimpleMan implements Lyricist { @Override public String Generate() { return " , "; } }
Register a class in the configuration file (immediately after the first bean)
<bean id="LyricistBean2" class="spring.impls.SimpleMan"/>
We try to create
Lyricist lyr1 = context.getBean("LyricistBean2", Lyricist.class); System.out.println(lyr1.Generate()); System.out.println(lyr1.hashCode()); Lyricist lyr2 = context.getBean("LyricistBean2", Lyricist.class); System.out.println(lyr2.Generate()); System.out.println(lyr2.hashCode());
The citizen is the same all the time. Disorder ...
Change the registration of the bean in the configuration file by adding the magic word scope = "prototype"
As a result, the
src \ main \ resources \ ApplicationContext.xml file will look like this:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="LyricistBean1" class="spring.impls.Poushkin" scope="singleton"/> <bean id="LyricistBean2" class="spring.impls.SimpleMan" scope="prototype"/> </beans>
Now everything is all right. Citizens are different every time. But Pushkin is always alone.
Attentive people noticed that the scope = "singleton" setting was added in the first bin, but this setting is used by default, so you can not write it.
That's all for today. If this post passes pre-moderation, and I have time and energy, there will be a continuation about AOP, JDBC, transactions, MVC and other wisdom.
Sincerely, Vladimir