1.目录结构
2.代码
2-1-1 IUser Dao解口
public interface IUserDao {
void add(User user);
void deleteById(Integer id);
void edit(User user);
}
2-1-2 IUser dao实现第一个1
//@Repository 表示当前是 数据 层
//"userDao" 表示 autowire="byName" 先根据名字查找,可以不加
@Repository("userDao")
public class UserDaoImpl implements IUserDao {
@Override
public void add(User user) {
System.out.println("添加用户: " + user);
}
@Override
public void deleteById(Integer id) {
System.out.println("删除用户: " + id);
}
@Override
public void edit(User user) {
System.out.println("编辑用户: " + user);
}
}
2-1-2 IUser dao实现第 2 个
@Repository
@Primary // primary="true" autowire="byType" 表示要使用相同的实现dao时,以此为主
public class UserDaoImplTwo implements IUserDao {
@Override
public void add(User user) {
System.out.println("Two 添加用户: " + user);
}
@Override
public void deleteById(Integer id) {
System.out.println("Two 删除用户: " + id);
}
@Override
public void edit(User user) {
System.out.println("Two 编辑用户: " + user);
}
}
2-2-1 实体类 IUser实体
@Data
public class User {
private Integer id;
private String name;
private String email;
}
2-3-1 IUser 服务层 接口
public interface IUserService {
void add(User user);
void deleteById(Integer id);
void edit(User user);
}
2-3-1 IUser 服务层 实现类
/**
* 当包扫描的时候,实例化之后纳入到容器中,命名规则是,将类的首字母小写,作为Bean的名字
*/
@Service
public class UserServiceImpl implements IUserService {
/**
* @Resource 扫描到属性头顶有这个注解,就相当于告诉spring IOC容器,我需要一个名为 userDao这样一个Bean,没有就根据类型找:
* 1.如果对应的类型的Bean就一个,直接注入。
* 2.如果对应的类型的Bean多个,就看是否有 @Primary 这个注解,如果有就以它为主;如果都没有就报错了。
*/
@Resource
private IUserDao userDao;
/** 可以通过构造器的方式实现注入
public UserServiceImpl(IUserDao userDao) {
this.userDao = userDao;
}
*/
@Override
public void add(User user) {
userDao.add(user);
}
@Override
public void deleteById(Integer id) {
userDao.deleteById(id);
}
@Override
public void edit(User user) {
userDao.edit(user);
}
}
3 test类 测试类
/**
* ComponentScan 叫做组件扫描(Bean扫描),参数是扫描包下的类
*/
@ComponentScan(basePackages = "org.example")
public class AnnotationContextTest {
public static void main(String[] args) {
/**
* 1.创建容器
* 2.会将构造方法中的类实例化然后纳入 IOC 容器。
* 3.然后会根据该类的头顶的 @ComponentScan 中的 basePackages指定的包,进行递归扫描。
* 4.扫描哪些类头顶上带了特定注解(@Service、@Repository)的类,将他们实例化然后放入到容器中。
* 5.并且会解析这些实例,实现注入:
* 1) 如果是构造方法的时候,那么在第4步,创建对象的时候就已经注入进来了。
* 2) 通过检测实例中属性上是否有 @Resource 注解,如果有,就找到对应的Bean注入进来。
*
*/
//传入的参数为当前类 AnnotationContextTest.class
ApplicationContext context = new AnnotationConfigApplicationContext(AnnotationContextTest.class);
// Stream.of(context.getBeanDefinitionNames()).forEach(System.out::println);
IUserService userService = context.getBean(IUserService.class);
userService.deleteById(455);
}
}
4 步骤
4-1.创建容器
4- 2.会将构造方法中的类实例化然后纳入 IOC 容器。
4-3.然后会根据该类的头顶的 @ComponentScan 中的 basePackages指定的包,进行递归扫描。
4-4.扫描哪些类头顶上带了特定注解(@Service、@Repository)的类,将他们实例化然后放入到容器中。
4-5.并且会解析这些实例,实现注入:
* 1) 如果是构造方法的时候,那么在第4步,创建对象的时候就已经注入进来了。
* 2) 通过检测实例中属性上是否有 @Resource 注解,如果有,就找到对应的Bean注入进来。
5. 注解解释
5-1 @Repository(“userDao”)
位置:类名
参数表示 autowire=“byName” 先根据名字查找,可以不加
@Resource 扫描到属性头顶有这个注解,就相当于告诉spring IOC容器,我需要一个名为 userDao这样一个Bean,没有就根据类型找:
* 1.如果对应的类型的Bean就一个,直接注入。
* 2.如果对应的类型的Bean多个,就看是否有 @Primary 这个注解,如果有就以它为主;如果都没有就报错了。
5-2 @ComponentScan(basePackages = “org.example”)
位置:类名
递归扫描包,参数化是包名
5-3 @Primary
位置:类名
primary=“true” autowire=“byType” 表示要使用相同的实现dao时,以此为主
5-4 @Service
位置:类名
表示 服务层 是被@ComponentScan扫描的组件
5-5-1 @resource 不推荐 等价于@autowire
位置:属性
需要注入的对象
5-5-2 通过构造器注入 和resource 二选一
public UserServiceImpl(IUserDao userDao) {
this.userDao = userDao;
}
5-5-3-1 @autowire 推荐 功能类似于resource
位置:属性
/**
@Autowired 扫描到属性头顶有这个注解,就相当于告诉spring IOC容器,我需要一个类型为IUserDao这样一个类型的Bean.
* 1.如果没找到,就报错;
* 2.如果找到了,存在多个,会报错,可以通过 @Primary 来解决这个问题。
* 3.如果找到了,存在多个,也没有加 @Primary 这个注解,会蜕变为根据名字来找, 即@Repository(“userDao”) 。
*
推荐使用构造器注入
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
5-5-3-2 @Qualifier(“userDaoImpl”)
它只是和@Autowired搭配使用的,在对应的类型中找到对应的名字
*/
@Qualifier(“userDaoImpl”)
表示找到dao的实现类有@repository的实现类userDaoImpl
,