用注解标识特定的组件,用组件扫描让系统自动找到特点的组件
实例:
1.创建4个包
(1)annotation
TestObject.java
import org.springframework.stereotype.Component;
@Component
public class TestObject {
}
Main.java
public class Main {
public static void main(String[] args) {
ApplicationContext act=new ClassPathXmlApplicationContext("bean-annotation.xml");
// TestObject testObject=(TestObject) act.getBean("testObject");
// System.out.println(testObject);
//
// UserService userService =(UserService) act.getBean("userService");
// System.out.println(userService);
//
// UserController userController=(UserController)act.getBean("userController");
// System.out.println(userController);
UserRepository userRepository=(UserRepository)act.getBean("userRepository");
System.out.println(userRepository);
}
}
(2)annotation.controller
UserController.java
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
public void execute() {
System.out.println("UserController execute...");
}
}
(3)annotation.repository
UserRepository.java
public interface UserRepository {
void save();
}
UserRepositoryImpl.java
import org.springframework.stereotype.Repository;
@Repository(value="userRepository")
public class UserRepositoryImpl implements UserRepository {
@Override
public void save() {
System.out.println("UserRepositoryImpl save...");
}
}
(4)annotation.service
UserService.java
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void add() {
System.out.println("UserService add...");
}
}
2.配置xml
<context:component-scan base-package="jjh.test.annotation"/>
3.运行结果
classpath扫描组件有两种方式过滤组件
1.context:include-filter 包含某种组件,该子节点必须满足use-default-filters=false
2.conext:exclude-filter 排除某种组件
type一下集中表达式,常用前两种
1.annotation 组件的全类名
如:org.springframework.stereotype.Repository;
org.springframework.stereotype.Service;
org.springframework.stereotype.Controller;
org.springframework.stereotype.Component;
2.assinable 包含类的全类名
组件装配
使用@Autowired 自动装配Bean
在UserController.java
下创建UserService并且给它打上注解@Autowired
@Controller
public class UserController {
@Autowired
private UserService userService;
public void execute() {
System.out.println("UserController execute...");
userService.add();
}
}
在UserService.java
下创建UserRepository并且给它打上注解@Autowired
系统自动创建UserService和UserRepository的bean
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public void add() {
System.out.println("UserService add...");
userRepository.save();
}
}
创建Main方法运行
public class Main {
public static void main(String[] args) {
ApplicationContext act=new ClassPathXmlApplicationContext("bean-annotation.xml");
// TestObject testObject=(TestObject) act.getBean("testObject");
// System.out.println(testObject);
//
// UserService userService =(UserService) act.getBean("userService");
// userService.add();
//
UserController userController=(UserController)act.getBean("userController");
userController.execute();
//
// UserRepository userRepository=(UserRepository)act.getBean("userRepository");
// System.out.println(userRepository);
}
}
运行结果
@Autowired也可以放在setter方法上
细节问题:
1.在上面的实例中,我在包下都有这些bean,如果没有呢
加入我将UserController.java的@Controller去掉,也就是消除这个组件
结果就是系统找不到这个bean,抛出异常
2.如果我有多个bean呢
比如我有两个类都是继承同一个接口并且标上注解,在其他的类中我通过接口创建实例,则会抛出异常,因为系统不知道你要用的是哪个bean(不知道创建哪个bean 的实例)
默认情况下:
推荐将@Autowired标注在setter方法上,因为系统可以根据实例名去找与其匹配的名
如我创建两个类
1.UserJdbcRepositoryImpl .class
@Repository("userRepository2")
public class UserJdbcRepositoryImpl implements UserRepository {
@Override
public void save() {
System.out.println("UserJdbcRepositoryImpl save...");
}
}
2.UserRepositoryImpl .class
@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {
@Override
public void save() {
System.out.println("UserRepositoryImpl save...");
}
}
两个类都在注解处取了别名
那么系统就会根据你setter中设置的形参来匹配名字比如
这里的形参名为userRepository2所有系统匹配UserJdbcRepositoryImpl
另一种方法是用@Qualifier指定,直接指定要用的bean
还有一种写法,将@Qualifier(name)加在参数名之前