Talking about the usage analysis of Spring framework annotations

As we all know, in the JavaEE development framework, the Spring framework is the most used, and the positioning of annotations in the framework is becoming more and more obvious. Tell a joke: what can be solved with one annotation, never solved with a bunch of configuration and code; if it can't be solved, then come with two annotations; (steady, don't spray...)

1. @Component is a general annotation defined by Spring, which can annotate any bean.

2. @Scope defines the scope of the bean, its default scope is "singleton", in addition to prototype, request, session and global session.

Case: @Component and @Scope usage analysis:

BeanAnnotation class:

@Scope
@Component
public class BeanAnnotation {

    public void say(String arg) {
        System.out.println("BeanAnnotation : " + arg);
    }

    public  void  myHashCode ()  {
        System.out.println("BeanAnnotation : " + this.hashCode());
    }

}

junit4 test class → TestBeanAnnotation class:

@RunWith(BlockJUnit4ClassRunner.class)
public class TestBeanAnnotation extends UnitTestBase {

    public TestBeanAnnotation() {
        super("classpath*:spring-beanannotation.xml");
    }

    @Test 
    public  void  testSay ()  {
        BeanAnnotation bean = super.getBean("beanAnnotation");
        bean.say("This is test.");
    }

    @Test 
    public  void  testScpoe ()  {
        BeanAnnotation bean = super.getBean("beanAnnotation");
        bean.myHashCode();
        bean = super.getBean("beanAnnotation");
        bean.myHashCode();
    }

}

Spring configuration file → spring-beanannotation.xml:

<context:component-scan base-package="com.beanannotation"></context:component-scan>

We first analyze from the Spring configuration file, base-package="com.beanannotation"indicating that we only process the annotations under this package name.

Then analyze the BeanAnnotation class, there is a say method. Assuming we don't know what type of class (Note: Service or DAO) this is, we can use a generic annotation @Component.

Finally, analyze the TestBeanAnnotation class. In the testSay method, super.getBean("beanAnnotation")the bean is obtained from the IOC container and the say method of the bean is called.

It's time to ask the question. When we super.getBean, we get it from the IOC container through the id of the bean, so what is this id? Because when we add @Component to the BeanAnnotation class, the default id is beanAnnotation. If the name of @Component is specified, for example @Component(”bean”), when the unit test is specified, the id obtained by super.getBean must be corresponding to it in order to test successfully.

Here I separate the @Scope annotation for analysis, and there is a testScpoe method in the TestBeanAnnotation class. There is a myHashCode method in the BeanAnnotation class, you may be a little confused, why use this.hashCode()? Because @Scope specifies the scope of the bean, in order to ensure that the result of the test class is accurate and clear, the hash code value is used to determine whether it is the same object.

3. @Repository, @Service, @Controller are more targeted annotations.

PS: Here we need to understand that these three annotations are based on the annotations defined by @Component:

①, @Repository is usually used to annotate DAO classes, which is what we often call the persistence layer.
②, @Service is usually used to annotate the Service class, that is, the service layer.
③, @Controller is usually used for the Controller class, that is, the control layer (MVC).

4. @Autowired is understood as a "traditional" setter method, which can be used in setter methods, constructors or member variables, and can perform automatic assembly of Spring Beans.

Case: @Autowired usage analysis 1:

Spring configuration file → spring-beanannotation.xml:

<context:component-scan base-package="com.beanannotation"></context:component-scan>

SimpleMovieLister类:

public  class  SimpleMovieLister  {

    private MovieFinder movieFinder;

    @Autowired(required=false)
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

}

By default, if a suitable bean cannot be found, it will cause autowiring to fail and throw an exception. We can annotate @Autowired on this set method and mark required=false to avoid it. However, this is not necessary. If an instance of movieFinder cannot be found, an exception will not be thrown. Only when movieFinder is found to be null when it is used, in this case, we are required to judge first when using it. Is movieFinder null, if so, a null pointer exception will be reported.

It is worth noting that we know that each class can have many constructors, but when using @Autowired, one and only one constructor can be marked as required=true (Note: the default value of required is false) .

Case: @Autowired usage analysis two:

BeanImplOne class:

@Order
@Component
public class BeanImplOne implements BeanInterface {

}

BeanImplTwo class:

@Order
@Component
public class BeanImplTwo implements BeanInterface {

}

BeanInterface class:

public interface BeanInterface {

}

BeanInvoker class:

@Component
public class BeanInvoker {

    @Autowired
    private List<BeanInterface> list;

    @Autowired
    private Map<String, BeanInterface> map;

    public void say() {
        if (null != list && 0 != list.size()) {
            for (BeanInterface bean : list) {
                System.out.println(bean.getClass().getName());
            }
        } else {
            System.out.println(" list is null !");
        }

        if (null != map && 0 != map.size()) {
            for (Map.Entry<String, BeanInterface> entry : map.entrySet()) {
                System.out.println(entry.getKey() + "      " + entry.getValue().getClass().getName());
            }
        } else {
            System.out.println("map is null !");
        }
    }
}

Test class TestInjection:

@RunWith(BlockJUnit4ClassRunner.class)
public class TestInjection extends UnitTestBase {

    public TestInjection() {
        super("classpath:spring-beanannotation.xml");
    }

    @Test 
    public  void  testMultiBean ()  {
        BeanInvoker invoker = super.getBean("beanInvoker");
        invoker.say();
    }

}

First of all, we know that the BeanImplOne class and the BeanImplTwo class implement the BeanInterface interface. We define the list and map in the BeanInvoker class. We annotate the BeanImplOne class and the BeanImplTwo class into it through the @Autowired annotation. So how to confirm that the @Autowired annotation injected these two classes into the list or map? Then look at the if loop statement and the foreach loop print. Through this logical judgment, if the path names of the BeanImplOne class and the BeanImplTwo class can be printed, it means that this is possible. If some friends may not believe it, you can try not to use the @Autowired annotation and see what the result is.

There is nothing to say about the test class. Have you noticed the @Order annotation? What needs to be explained here is that if the execution number, such as 1 or 2, is entered in the @Order annotation, the printed path names will be in order, that is to say, the priority function can be achieved by specifying the content of the @Order annotation.

5. The @ImportResource annotation introduces a resource, corresponding to an xml file

6. The @Value annotation takes its key from the resource file and assigns it to the member variable of the current class

Case: @ImportResource and @Value usage analysis:

MyDriverManager class:

public  class  MyDriverManager {

    public MyDriverManager(String url, String userName, String password) {
        System.out.println("url : " + url);
        System.out.println("userName: " + userName);
        System.out.println("password: " + password);
    }

}

config.xml:

<context:property-placeholder location="classpath:/config.properties"/>

StoreConfig class:

@Configuration
@ImportResource("classpath:config.xml")
public class StoreConfig {

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    @Bean
    public MyDriverManager myDriverManager() {
        return new MyDriverManager(url, username, password);
    }

In this case, we use annotations to configure the connection to the jdbc database. First, create a MyDriverManager class with a constructor, then configure the resource file path in config.xml so that the @ImportResource annotation can be obtained, and finally configure the StoreConfig class. (Note that url, username, password must also be consistent with the database)

Explain the StoreConfig class in detail: First, we define three member variables, and then annotate each member variable with a @value annotation. Note that the content in @value must be the key value in the resource file. The @ImportResource annotation here is to specify a resource file, and the corresponding data is obtained in this resource file. So what is the @Configuration annotation used for? Why not use the @Component annotation? In fact, this is the case. The @Component annotation is used to load the marked classes into the Spring environment. At this time, you need to configure component-scan to use it, and the @Configuration annotation is an annotation provided after Spring 3.X, which is used for Instead of XML to configure Spring.

7. The @Bean annotation is used to identify the method of configuring and initializing a new object managed by the SpringIOC container, similar to the <bean/> of the configuration file in XML

ps:默认的@Bean注解是单例的,那么有什么方式可以指定它的范围呢?所以这里才出现了@Scope注解

8.@Scope注解,在@Scope注解里面value的范围和Bean的作用域是通用的,proxyMode的属性是采用哪一种的单例方式(一种是基于接口的注解,一种是基于类的代理)

案例:@Bean和@Scope用法分析:

    @Bean
    @Scope(value ="session",proxyMode = "scopedProxyMode.TARGET_CLASS")
    public UserPreferences userPreferences(){
        return new userPreferences();
    }

    @Bean
    public service userService(){
        UserService service =new SimpleUserService();
        service.setUserPreferences(userPreferences);
        return service;
    }

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326491586&siteId=291194637