Explain the usage of annotations in Java's Spring framework

Reprint: http://www.jb51.net/article/75460.htm

 

1. Use Spring annotations to inject properties


1.1. The implementation of the class how we inject properties before using annotations  :

class UserManagerImpl implements UserManager {
  private UserDao userDao;
  public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
  }
  ...
}

Configuration file:

<bean id="userManagerImpl" class="com.kedacom.spring.annotation.service.UserManagerImpl">
  <property name="userDao" ref="userDao" />
</bean>
<bean id="userDao" class="com.kedacom.spring.annotation.persistence.UserDaoImpl">
  <property name="sessionFactory" ref="mySessionFactory" />
</bean>

1.2. Introduce the @Autowired annotation (not recommended, @Resource is recommended) 
class implementation (annotate member variables)

public class UserManagerImpl implements UserManager {
  @Autowired
  private UserDao userDao;
  ...
}

or (annotate the method)

UserManagerImpl implements UserManager {
  private UserDao userDao;
  @Autowired
  public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
  }
  ...
}

configuration file

<bean id="userManagerImpl" class="com.kedacom.spring.annotation.service.UserManagerImpl" />
<bean id="userDao" class="com.kedacom.spring.annotation.persistence.UserDaoImpl">
  <property name="sessionFactory" ref="mySessionFactory" />
</bean>

@Autowired can annotate member variables, methods and constructors to complete the work of autowiring. In the above two different implementation methods, the annotation position of @Autowired is different. They will automatically install the userDao attribute when Spring initializes the userManagerImpl bean. The difference is: in the first implementation, Spring will directly assign the only one of the UserDao type. The bean is assigned to the member variable userDao; in the second implementation, Spring will call the setUserDao method to assemble the only bean of type UserDao to the userDao property.

1.3. Make @Autowired work 
To make @Autowired work, you also need to add the following code to the configuration file

class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />

1.4. @Qualifier 
@Autowired is autowired based on the type. In the above example, if there is more than one bean of type UserDao in the Spring context, a BeanCreationException will be thrown; if there is no bean of type UserDao in the Spring context, a BeanCreationException will also be thrown. We can use @Qualifier with @Autowired to solve these problems. 
1. There may be multiple instances of UserDao

@Autowired
public void setUserDao(@Qualifier("userDao") UserDao userDao) {
  this.userDao = userDao;
}

In this way, Spring will find the bean whose id is userDao for assembly. 
2. There may not be an instance of UserDao

@Autowired(required = false)
public void setUserDao(UserDao userDao) {
  this.userDao = userDao;
}

1.5. @Resource (JSR-250 standard annotation, it is recommended to use it instead of Spring's proprietary @Autowired annotation) 
Spring not only supports its own @Autowired annotation, but also supports several annotations defined by the JSR-250 specification, which are @Resource, @PostConstruct, and @PreDestroy. 
The role of @Resource is equivalent to @Autowired, except that @Autowired is automatically injected according to byType, while @Resource is automatically injected according to byName by default. @Resource has two important attributes, namely name and type. Spring parses the name attribute of the @Resource annotation as the name of the bean, and the type attribute parses it as the type of the bean. So if the name attribute is used, the automatic injection strategy of byName is used, and the automatic injection strategy of byType is used when the type attribute is used. If neither the name nor the type attribute is specified, the strategy will be automatically injected using byName through the reflection mechanism. 
@Resource assembly order

If both name and type are specified, a unique matching bean will be found from the Spring context for assembly, and an exception will be thrown
if not found. If name is specified, a bean with a matching name (id) will be searched from the context for assembly, if not found
If the type is specified, the only bean matching the type will be found in the context for assembly. If no or more than one is found, an exception will be thrown. If
neither name nor type is specified, it will automatically follow byName method for assembly (see 2); if there is no match, it falls back to a primitive type (UserDao) for matching, and if it matches, it is automatically assembled;
1.6. @PostConstruct (JSR-250) 
adds the annotation @PostConstruct to the method, this The method will be executed by the Spring container after the bean is initialized (Note: Bean initialization includes, instantiating the bean, and assembling the properties of the bean (dependency injection)). 
A typical application scenario of it is when you need to inject a property defined in its parent class into a bean, and you cannot override the parent class property or property setter method, such as: 

public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
  private SessionFactory mySessionFacotry;
  @Resource
  public void setMySessionFacotry(SessionFactory sessionFacotry) {
    this.mySessionFacotry = sessionFacotry;
  }
  @PostConstruct
  public void injectSessionFactory() {
    super.setSessionFactory(mySessionFacotry);
  }
  ...
}

Here, through @PostConstruct, a sessionFactory private property defined in the parent class of UserDaoImpl is injected into our own sessionFactory (the setSessionFactory method of the parent class is final and cannot be overridden), and then we can call super.getSessionFactory() to get access this property.


1.7. @PreDestroy (JSR-250) 
Add the annotation @PreDestroy to the method, and this method will be executed by the Spring container after the bean is initialized. Since we don't currently have a scene where we need to use it, we won't demonstrate it here. Its usage is the same as @PostConstruct.

1.8. Simplified configuration using <context:annotation-config /> 
Spring 2.1 adds a new context schema namespace, which provides convenient configuration for annotation-driven, property file import, load-time weaving and other functions. We know that the annotation itself doesn't do anything, it only provides metadata information. For metadata information to really work, the processors responsible for handling that metadata must work. 
AutowiredAnnotationBeanPostProcessor and CommonAnnotationBeanPostProcessor are the processors that process these annotation metadata. But defining these beans directly in the Spring configuration file is clumsy. Spring provides us with a convenient way to register these BeanPostProcessors, which is <context:annotation-config />:

<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-2.5.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-2.5.xsd">
  <context:annotation-config />
</beans>

<context:annotationconfig /> will implicitly register the four BeanPostProcessors AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor, PersistenceAnnotationBeanPostProcessor and RequiredAnnotationBeanPostProcessor with the Spring container.

2. Use Spring annotation to complete the definition of bean. 
Above we have introduced the function of automatic injection in bean through @Autowired or @Resource. Next, we will introduce how to annotate bean, so as to completely remove the configuration of bean definition from the XML configuration file .

2.1. @Component (deprecated), 
@Repository, @Service, @Controller only need to add a @Component annotation to the corresponding class to define the class as a Bean:

@Component
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
  ...
}

For beans defined with the @Component annotation, the default name (id) is an unqualified class name starting with lowercase. The Bean name defined here is userDaoImpl. You can also specify the name of the bean: 
@Component("userDao") 
@Component is the general form of all Spring-managed components, and Spring also provides more detailed annotation forms: @Repository, @Service, @Controller, which correspond to Storage layer beans, business layer beans, and presentation layer beans. In the current version (2.5), these annotations have the same semantics as @Component and are completely generic. More semantics may be added to them in future versions of Spring. Therefore, we recommend using @Repository, @Service, @Controller instead of @Component.

2.2. Using <context:component-scan /> to make bean definition annotations work

<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-2.5.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-2.5.xsd">
  <context:component-scan base-package="com.kedacom.ksoa" />
</beans>

Here, all the configuration content that defines beans through the <bean> element has been removed, and only one line of <context:component-scan /> configuration needs to be added to solve all problems - the Spring XML configuration file has been extremely simplified (of course the configuration Metadata is still needed, just in the form of comments). The base-package attribute of <context:component-scan /> specifies the class package to be scanned. All classes in the class package and its recursive subpackages will be processed. 
<context:component-scan /> also allows defining filters to include or exclude certain classes under the base package. Spring supports the following 4 types of filtering methods:

Filter type expression example description
Annotation org.example.SomeAnnotation Filter out all classes annotated with SomeAnnotation.
Class name specified org.example.SomeClass Filter specified class
Regular expression com\.kedacom\.spring\.annotation\.web \..* Filter some classes by regular expressions
AspectJ expressions org.example..*Service+ Filter some classes by AspectJ expressions

Taking regular expressions as an example, I list an application example:

<context:component-scan base-package="com.casheen.spring.annotation">
  <context:exclude-filter type="regex" expression="com\.casheen\.spring\.annotation\.web\..*" />
</context:component-scan>

It is worth noting that the <context:component-scan /> configuration item not only enables the scanning of class packages to implement annotation-driven bean definitions, but also enables annotation-driven automatic injection (that is, it is also implicitly registered internally AutowiredAnnotationBeanPostProcessor and CommonAnnotationBeanPostProcessor), so when using <context:component-scan />, you can remove <context:annotation-config />.

2.3. Use @Scope to define the scope 
of a bean When using XML to define a bean, we may also need to define the scope of a bean through the bean's scope attribute. We can also use the @Scope annotation to complete this work:

@Scope("session")
@Component()
public class UserSessionBean implements Serializable {
  ...
}

3. Define the relationship between the three beans before using annotation like this

package com.baobaotao;
public class Office {
  private String officeNo =”001”;
 
  // omitted get / setter
 
  @Override
  public String toString() {
    return "officeNo:" + officeNo;
  }
}

ackage com.baobaotao;
 
public class Car {
  private String brand;
  private double price;
 
  // Omitted get / setter
 
  @Override
  public String toString() {
    return "brand:" + brand + "," + "price:" + price;
  }
}

package com.baobaotao;
 
public class Boss {
  private Car car;
  private Office office;
 
  // Omitted get / setter
 
  @Override
  public String toString() {
    return "car:" + car + "\n" + "office:" + office;
  }
}

The configuration file is as follows:

<?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-2.5.xsd">
  <bean id="boss" class="com.baobaotao.Boss">
    <property name="car" ref="car"/>
    <property name="office" ref="office" />
  </bean>
  <bean id="office" class="com.baobaotao.Office">
    <property name="officeNo" value="002"/>
  </bean>
  <bean id="car" class="com.baobaotao.Car" scope="singleton">
    <property name="brand" value=" 红旗 CA72"/>
    <property name="price" value="2000"/>
  </bean>
</beans>

The test file is as follows:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AnnoIoCTest {
 
  public static void main(String[] args) {
    String[] locations = {"beans.xml"};
    ApplicationContext ctx =
      new ClassPathXmlApplicationContext(locations);
    Boss boss = (Boss) ctx.getBean("boss");
    System.out.println(boss);
  }
}

 
4. Next, we can use autowired to annotate , he can standardize member variables, methods and constructors to complete the work of autowiring.

autoware to annotate the usage of member variables

package com.baobaotao;
import org.springframework.beans.factory.annotation.Autowired;
 
public class Boss {
 
  @Autowired
  private Car car;
 
  @Autowired
  private Office office;
 
}

The corresponding configuration files are as follows:

<?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-2.5.xsd">
 
  <!-- The BeanPostProcessor will work automatically and automatically inject beans marked with @Autowired -->
  <bean class="org.springframework.beans.factory.annotation.    AutowiredAnnotationBeanPostProcessor"/>
 
  <!-- Remove the information of the property injection configuration of the boss bean-->
  <bean id="boss" class="com.baobaotao.Boss"/>
 
  <bean id="office" class="com.baobaotao.Office">
    <property name="officeNo" value="001"/>
  </bean>
  <bean id="car" class="com.baobaotao.Car" scope="singleton">
    <property name="brand" value=" 红旗 CA72"/>
    <property name="price" value="2000"/>
  </bean>
</beans>

Autoware can also be used on setter methods and constructors

package com.baobaotao;
 
public class Boss {
  private Car car;
  private Office office;
 
   @Autowired
  public void setCar(Car car) {
    this.car = car;
  }
 
  @Autowired
  public void setOffice(Office office) {
    this.office = office;
  }
}

package com.baobaotao;
 
public class Boss {
  private Car car;
  private Office office;
 
  @Autowired
  public Boss(Car car ,Office office){
    this.car = car;
    this.office = office ;
  }
 
}

When the number of candidate beans is 0, we can use @Autowired(required = false) to prevent spring from reporting an error when the bean cannot be found.

When there are multiple candidate beans, we can specify the name of the injected bean through the @Qualifier annotation.

When @Autowired is used in combination with @Qualifier, the auto-injection strategy is changed from byType to byName. @Autowired can annotate member variables, methods, and constructors, while @Qualifier's annotation objects are member variables, method parameters, and constructor parameters. It is because of the difference of annotation objects that Spring does not unify @Autowired and @Qualifier into one annotation class.

5. @resort is based on the name to reflect , he has two parameters, name and type, use name to map according to byname, use type to map according to bytype.

package com.baobaotao;
 
import javax.annotation.Resource;
 
public class Boss {
  // Automatically inject beans of type Car
  @Resource
  private Car car;
 
  // Automatically inject the bean with the bean name office
  @Resource(name = "office")
  private Office office;
}
@postconstructor and preDestory are used to annotate methods after class initialization and before destruction.


package com.baobaotao;
 
import javax.annotation.Resource;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
 
public class Boss {
  @Resource
  private Car car;
 
  @Resource(name = "office")
  private Office office;
 
  @PostConstruct
  public void postConstruct1(){
    System.out.println("postConstruct1");
  }
 
  @PreDestroy
  public void preDestroy1(){
    System.out.println("preDestroy1");
  }
}

6. @compent can define beans directly , so there is no need to configure beans in the xml configuration file

package com.baobaotao;
 
import org.springframework.stereotype.Component;
 
@Component
public class Car {
}

package com.baobaotao;
 
import org.springframework.stereotype.Component;
 
@Component
public class Office {
  private String officeNo = "001";
}

package com.baobaotao;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
 
@Component("boss")
public class Boss {
  @Autowired
  private Car car;
 
  @Autowired
  private Office office;
}

@Component has an optional input parameter to specify the name of the bean. In Boss, we define the bean name as "boss". In general, beans are singletons, and the places where beans need to be injected only need to be injected automatically through the byType strategy, so there is no need to specify the name of the bean.

<?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-2.5.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context-2.5.xsd">
  <context:component-scan base-package="com.baobaotao"/>
</beans>

7. @scope can be used to specify its target

package com.baobaotao;
import org.springframework.context.annotation.Scope;
@Scope("prototype")
@Component("boss")
public class Boss {


In addition to providing @Component annotations, Spring 2.5 also defines several annotations with special semantics, they are: @Repository, @Service and @Controller. In the current Spring version, these three annotations are equivalent to @Component, but from the naming of the annotation classes, it is easy to see that these three annotations are related to the persistence layer, business layer and control layer (Web layer). correspond. Although these three annotations are nothing new compared to @Component, Spring will add special functionality to them in future releases. Therefore, if the Web application adopts a classic three-tier hierarchical structure, it is best to annotate the classes in the hierarchy with @Repository, @Service and @Controller in the persistence layer, business layer and control layer respectively, and use @ Component annotates the more neutral classes.

 

Guess you like

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