Spring提供了组件扫描,来进行对指定包进行扫描,对拥有注解的类进行实例化等操作。
<context:component-scan base-package="com.pngyul.domain">context:component-scan>
beans>
Spring从2.0开始引入基于注解的配置方式,并且不断的进行完善。通过注解的方式可以直接在类上定义Bean的信息,非常方便。
@Component注解来对类进行标注,它可以被Spring容器识别,Spring容器将自动将类转换为容器管理的Bean。
//使用@Component注解定义Bean ,和是等效的。
@Component("account")
public class Account {
private int id;
private String name;
private String money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMoney() {
return money;
}
public void setMoney(String money) {
this.money = money;
}
@Override
public String toString() {
return "Account [id=" + id + ", name=" + name + ", money=" + money + "]";
}
}
除了@Component外,Spring提供了三个功能和@Component等效的注解。
它们一般用于web项目,对DAO,service,web层进行注解,所以也称为Bean的衍生注解。
@Repository:对DAO实现类进行注解
@Service:对service实现类进行注解
@Controller:对web层Controller实现类进行注解
之所以提供这三个特殊的注解,是为了让注解类本身的用途清晰化,此外,Spring还赋予了一些特殊的功能。我们在项目开发中应该尽量使用这种形式
通过注解配置的Bean和通过< bean >配置的Bean一样,默认的作用范围都是singleton,Spring为注解配置提供了一个@Scope的注解,显式指定Bean的作用范围。
@Controller("user")
//指定作用范围为多例prototype
@Scope("prototype")
public class User {
public void say(){
System.out.println("hello.word");
}
}
Spring定义的@PostConstruct和@PreDestroy两个注解相当于bean的init-method和destory-method属性的功能
@Controller("account")
@Scope("prototype")
public class Account {
public void save() {
System.out.println("hello.word");
}
@PostConstruct
public void myinit() {
System.out.println("初始化....");
}
@PreDestroy
public void mydestory() {
System.out.println("销毁中....");
}
}
Spring为我们提供了注解 @value,用于对一般属性注入,可以不用提供set方法
@Value("Tom")
private String nmae;
@Value("22")
private int age;
//它是通过反射的Field赋值,破坏了封装性
提供set方法的也可以这样注入
@Value("Tom")
Public void setName(String name){
this.name = name;
}
//通过set方法赋值,推荐使用.
然而在实际开发者中,尽管实际是破坏了对象的封装性,但开发者还是喜欢用第一种方式注入属性
//会根据类型自动注入
@Autowired
private UserService userservice;
//@Autowired可以对类成员变量的set方进行注解。
//对set方法使用注解,UserDao的实例就会被注入进来
@Autowired
public void setUserdao(UserDao userdao){
this.userdao=userdao;
}
问题:@Autowired默认按类型匹配的方式,在容器中查找匹配的Bean,当有且只有一个匹配的Bean时,Spring将其注入到@Autowired注解的变量中。但是如果容器中有超过一个以上的匹配Bean时,例如有两个UserService类型的Bean,这时就不知道将哪个Bean注入到变量中,就会出现异常
为了解决这个问题,Spring可以通过@Qualifier注解来注入指定Bean的名称。
public class UserAction {
@Autowired
//指定指定Bean的名称
@Qualifier("userservice")
private UserService userservice;
}
还有一种更为便捷的注解方式注入属性@Resource,相当于@Autowired 和@Qualifier一起使用
@Resource(name="userservice")
private UserService userservice;
对于一个大型项目而言,可能有多个XML配置文件,在启动Spring容器时,可以通过一个String数组指定这些配置文件。Spring还允许我们通过< import >标签将多个配置文件引入到一个文件中,进行配置文件的集成,这样启动Spring容器时,就仅需指定这个合并好的配置文件即可。
ApplicationContext ac=new ClassPathXmlApplicationContext(new String[]{"bean1.xml","bean2.xml"});
//resource属性指定配置文件位置,支持Spring标准的资源路径
<import resource="classthpath:com/cad/domain/bean1.xml"/>
<import resource="classthpath:com/cad/domain/bean2.xml"/>
第一种方式并不容易维护,我们在开发中推荐使用第二种方式。
以前,我们在测试的时候,都要写 ApplicationContext ac=new ClassPathXmlApplicationContext(“applicationContext.xml”),然后再获取bean对象。
现在使用JUnit,可以直接使用注解来配置,不再需要手写代码
例如下面这个例子:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo {
@Resource(name="accountService")
private AccountService as;
@Test
public void fun1(){
as.transfer(1, 2, 100d);
}