这篇文章记录Spring IoC通过注解注入属性的方法。
一、注解注入属性一个简单的案例
1)Spring配置文件引入context约束
<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.xsd">
</beans>
2)Spring配置文件中开启注解扫描
<context:component-scan base-package="com.pc.service"/>
注意,在第一步必须要引入context约束,否则无法出现context标签。
3)在类上添加@Component注解
@Component("user")
public class User {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
4)编写测试
ApplicationContext act = new ClassPathXmlApplicationContext("beans-ioc.xml");
User user = (User) act.getBean("user");
System.out.println(user);
二、Spring IoC常用注解详解
1)Bean标注注解
- @Component :组件通用注解,常用于Model类
- @Controller :常用于对Controller实现类进行标注
- @Service:常用于对Service实现类进行标注
- @Repository:常用于对DAO实现类进行标注
@Component是Spring提供的通用的组件注解。@Component、@Controller、@Service和@Repository功能一样,可以互换,我们使用不同注解主要为了区分被注解的类处在不同的业务层,使逻辑更加清晰。这四个注解主要是定义bean,创建bean。
它们使用方法:
(1)标注在类上
(2)@Component("name")等于@Component(value="user")
(3)@Component相当于@Component("className")
2)Bean属性注入注解
- @Value :注入普通类型属性
- @Resource :注入对象类型
- @Autowired :注入对象类型,默认按照类型注入。结合@Qualifier注解完成按名称的注入。
(1)@Value注解
例如,为上面案例中User类中id和name一个初始值,我们可以在id和name属性上面使用@Value注解,也可以在它们的set方法上使用@Value注解
@Component(value="user")
public class User {
@Value("1")
private Integer id;
@Value("lzgsea")
private String name;
public Integer getId() {
return id;
}
//@Value("1")
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
//@Value("lzgsea")
public void setName(String name) {
this.name = name;
}
}
(2)@Resource :注入对象类型
public class UserTest {
@Resource(name = "user")
private User user;
}
(3)@Autowired注解
public class UserTest {
// 按名注入,需要组件设置名称
// @Resource(name = "user")
// 和上面功能一样,按名注入
@Qualifier("user")
@Autowired
private User user;
}
3)Bean的作用范围注解@Scope
Bean的范围的注解:默认是单例的。
@Scope :在类上添加的,控制类生成的时候采用单例还是多例。
@Scope取值:
- singleton :单例
- prototype :多例
- request :request域,需要在web环境
- session :session域,需要在web环境
- application: context域,需要在web环境
- globalsession 集群环境的session域,需要在web环境
4)Bean的生命周期注解
@PostConstruct :相当于init-method
@PreDestroy :相当于destroy-method
这两注解用在方法上面。
@PostConstruct
public void init() {
System.out.println("初始化方法......");
}
@PreDestroy
public void destroy() {
System.out.println("销毁方法......");
}
三、context:componet-scan
配置<context:annotation-config>后,会扫描@Required、@Autowired、@PostConstruct、@PreDestroy、@Resource等注解。
配置<context:component-scan base-package="xx">标签后,spring可以自动去扫描base-pack下面或者子包下面的java文件,除了扫描<context:annotation-config>中所有的注解,还会扫描@Component、@Repository、@Service、@Controller、 @RestController、@ControllerAdvice、@Configuration 这些注解。
<context:component-scan>提供了两个子标签
- <context:include-filter>
- <context:exclude-filter>
在说明这两个子标签前,先说一下<context:component-scan>有一个use-default-filters属性,该属性默认为true,这就意味着会扫描指定包下的全部的标有Spring注解的类,并注册成bean。也就是@Component,@Controller,@Service,@Reposity等。所以如果仅仅是在配置文件中这么写
<context:component-scan base-package="lzgsea.*"/>
use-default-filter此时为true那么会对base-package包或者子包下的所有的进行java类进行扫描,并把匹配的java类注册成bean。
可以发现这种扫描的粒度有点太大,如果你只想扫描指定包下面的Controller,该怎么办?此时子标签<context:incluce-filter>就起到了勇武之地。如下所示
<context:component-scan base-package="lzgsea.*" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
这样就会只扫描base-package包或者子包下所有@Controller下的java类,并注册成bean。
use-dafault-filter在上面并没有指定,默认就为true,或者直接use-dafault-filter改为true,那么会对base-package包或者子包下的所有的进行java类进行扫描。
<context:component-scan base-package="lzgsea.*">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
此时,spring不仅扫描了@Controller,还扫描了指定包所在的子包service包下注解@Service的java类。此时指定的include-filter不任何起到作用。
另外在我参与的项目中可以发现在base-package指定的包中有的子包是不含有注解了,所以不用扫描,此时可以指定<context:exclude-filter>来进行过滤,说明此包不需要被扫描。
综合以上说明:
use-default-filters="false"的情况下不会自动扫描,需要配置<context:include-filter>指定扫描哪些注解
use-dafault-filters="false"的情况下:<context:include-filter>指定的扫描。
use-default-filters="true"的情况下:<context:exclude-filter>指定的不扫描