Spring4.0 study notes (4)

Configure beans based on annotations

scan the classpath for components

  • Component scanning: Spring can automatically scan,
    detect and instantiate components with specific annotations from the classpath.

  • Specific components include

    • @Component: Basic annotation, identifies a Spring-managed component
    • @Respository: Identifies persistence layer components
    • @Service: identifies service layer (business layer) components
    • @Controller: Identifies presentation layer components
  • For scanned components, Spring has a default naming strategy : use an unqualified class name, the first letter is lowercase. You can also use the value attribute value in the annotation to identify the name of the component
  • When a specific annotation is used on the component class, it is also necessary to declare context:component-scan in the Spring configuration file
    • The base-package attribute specifies a base class package to be scanned, and the Spring container will scan all classes in this base class package and its subpackages.
    • When multiple packages need to be scanned, commas can be used to separate them .
    • If you only want to scan a specific class and not all classes under the base package, you can use the resource-pattern attribute to filter specific classes
    • The context:include-filter child node represents the target class to be included
    • context:exclude-filter child node represents the target class to be excluded
    • There can be several context:include-filter and context:exclude-filter child nodes under context:component-scan
    • The context:include-filter and context:exclude-filter subnodes support several types of filter expressions:
    • write picture description here
      code
      -package structure
      write picture description here
    <!-- 导入 context 命名空间 , 导入 spring-aop-4.0.2.RELEASE.jar -->
    <!-- 指定 Spring IOC 容器扫描的包 -->
    <!-- 可以通过 resource-pattern 来指定扫描的资源 -->
    <!-- 
    <context:component-scan base-package="com.anqi.anotation"
        resource-pattern="repository/*.class"></context:component-scan>
     -->

     <!-- context:exclude-filter 子节点指定排除哪些指定表达式的组件 -->
     <!--  
    <context:component-scan base-package="com.anqi.anotation">
        <context:exclude-filter type="annotation" 
            expression="org.springframework.stereotype.Repository"/>
        <context:exclude-filter type="annotation" 
            expression="org.springframework.stereotype.Repository"/>
    </context:component-scan>
    -->

    <!-- 
        context:include-filter 子节点指定包含哪些表达式的组件, 该子节点需要 use-default-filters 
            配合使用 
        use-default-filters 默认为 true 表示会扫描包下的所有资源    
    -->
    <context:component-scan base-package="com.anqi.anotation" use-default-filters="false">
        <!--
        <context:include-filter type="annotation" 
            expression="org.springframework.stereotype.Repository"/> -->
        <context:include-filter type="assignable" 
            expression="org.springframework.stereotype.Repository"/>

    </context:component-scan>
import org.springframework.stereotype.Component;

@Component
public class TestObject {
}
import org.springframework.stereotype.Controller;
@Controller
public class UserController {

    public void execute() {
        System.out.println("UserController excute");
    }
}
public interface UserRepository {
    void save();
}
import org.springframework.stereotype.Repository;
@Repository("userRepository")
public class UserRepositoryIml implements UserRepository {

    public void save() {
        System.out.println("UserRespository save..");
    }

}
import org.springframework.stereotype.Service;
@Service
public class UserService {
    public void add() {
        System.out.println("UserService ..add");
    }
}
public class Main {

    public static void main(String[] args) {

        ApplicationContext ctx = new 
                ClassPathXmlApplicationContext("bean-annotation.xml");

        TestObject testObject = (TestObject) ctx.getBean("testObject");
        System.out.println(testObject);

        UserController userController = (UserController) ctx.getBean("userController"); 
        System.out.println(userController);

        UserService userService = (UserService) ctx.getBean("userService"); 
        System.out.println(userService);

        UserRepositoryIml userRepositoryIml = (UserRepositoryIml) ctx.getBean("userRepository");
        System.out.println(userRepositoryIml);
    }

}

Component assembly

Autowire beans with @Autowired

The @Autowired annotation autowires a single bean property with compatible types

  • Constructors, normal fields (even non-public), all methods with parameters can be annotated with @Authwired
  • By default, all properties annotated with @Authwired need to be set. When Spring cannot find a matching bean assembly property, an exception will be thrown . If a property is not allowed to be set, you can set the required property of the @Authwired annotation false
  • By default, when there are multiple beans of compatible types in the IOC container, autowiring by type will not work. In this case, the name of the bean can be provided in the @Qualifier annotation . Spring allows the input parameters of methods to be marked with @Qualifiter Specifies the name of the injected bean

  • The @Authwired annotation can also be applied to properties of an array type, in which case Spring will autowire all matching beans.

  • The @Authwired annotation can also be applied to collection properties, in which case Spring reads the type information of the collection and autowires all compatible beans.

  • When the @Authwired annotation is used on java.util.Map, if the key value of the Map is String, then Spring will automatically assemble a bean that is compatible with the type of the Map value, and the name of the bean is used as the key value.

<context:component-scan base-package="com.anqi.anotation">

</context:component-scan>
import org.springframework.stereotype.Component;
@Component
public class TestObject {
}
@Controller
public class UserController {
    @Autowired
    private UserService userService;
    public void execute() {
        System.out.println("UserController excute");
        userService.add();
    }
}
public interface UserRepository {
    void save();
}
@Repository("userRespository")
//修改bean的名称,在 main 函数 可以 getBean("userRespository")来获取
public class UserRepositoryIml implements UserRepository {
    @Autowired
    private TestObject testObject;

    public void save() {
        System.out.println("UserRespository save..");
        System.out.println(testObject);
    }

}
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;  
    /*  
        与上方效果一样             
        @Autowired
        public void setUserRepository(UserRepository userRepository) {
            this.userRepository = userRepository;
    }*/

    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    public void add() {
        System.out.println("UserService ..add");
        userRepository.save();
    }

}

If the TestObject is not annotated, that is, not loaded into the IOC, the reference will report an error

public class TestObject {
}

So how to make the reference value null instead of reporting an error?

@Repository("userRespository")
public class UserRepositoryIml implements UserRepository {

    @Autowired(required=false)
    private TestObject testObject;

    public void save() {
        System.out.println("UserRespository save..");
        System.out.println(testObject);
    }

}

What if two classes implement the same interface?

@Repository
public class UserJdbcRepositoryIpl implements UserRepository {

    public void save() {
        System.out.println("UserJdbcRepositoryIpl...");
    }

}
@Repository("userRespository")
public class UserRepositoryIml implements UserRepository {

    @Autowired(required=false)
    private TestObject testObject;

    public void save() {
        System.out.println("UserRespository save..");
        System.out.println(testObject);
    }

}

You can take @Qualifier("userJdbcRepositoryIpl") to specify that the first letter should also be lowercase

@Service
public class UserService {

    @Autowired
    @Qualifier("userJdbcRepositoryIpl")
    private UserRepository userRepository;  
    /*  
        与上方效果一样             
        @Autowired
        public void setUserRepository(UserRepository userRepository) {
            this.userRepository = userRepository;
    }*/

    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    public void add() {
        System.out.println("UserService ..add");
        userRepository.save();
    }

}

Autowire beans with @Resource or @Inject

  • Spring also supports @Resource and @Inject annotations, which are similar to @Autowired annotations
  • The @Resource annotation requires a property of the bean name. If the property is empty, the variable or method name at the annotation will be automatically used as the name of the bean.
  • @Inject, like @Autowired annotation, also matches injected beans by type, but does not have the reqired attribute
  • It is recommended to use the @Autowired annotation

New in Spring 4.x: Generic Dependency Injection

In Spring 4.x, a reference to a member variable of the generic type corresponding to the subclass can be injected into the subclass

write picture description here

<context:component-scan base-package="com.anqi.generic.di"></context:component-scan>
public class BaseRepository<T> {

}
public class BaseService<T> {

    @Autowired
    private BaseRepository<T> repository;

    public void add() {
        System.out.println("BaseService add..");
        System.out.println(repository);
    }
}
@Repository
public class UserRepository extends BaseRepository<User>{

}
@Service
public class UserService extends BaseService<User>{
}
public class User {
}
public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new
                ClassPathXmlApplicationContext("bean-generic-di.xml");

        UserService service = (UserService) ctx.getBean("userService");
        service.add();
        //BaseService add..
        //com.anqi.generic.di.UserRepository@4d3167f4
    }
}

Guess you like

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