在pom.xml
中添加Spring的上下文和管理对象模块
org.springframework spring-context 5.2.3.RELEASE org.springframework spring-beans 5.2.3.RELEASE
在resource目录下新建一个xml
文件,并配置Spring组件的扫描路径
也就是说,只有在com.demo
下的类才有可能被存储到Spring当中
1.类注解:@Controller[控制器]、@Service[业务逻辑类]、@Repository[数据持久类]、@Component[组件类]、@Configuration[配置类]
2.方法注解:@Bean
@Controller // 将当前的类存储到 Spring 中
public class UserController {/*** 对象中的测试方法* @param name*/public void testHello(String name) {System.out.println("hello Controller " + name);}
}
注意事项:
@Service //将当前对象存储到 Spring 当中
public class UserService {public void printService(String name) {System.out.println("hello Service "+name);}
}
@Repository // 将对象存储到 Spring中
public class UserRepository {public void printRepository(String name) {System.out.println("hello repository "+name);}
}
@Component //将对象存储到Spring中
public class UserComponent {public void printComponent(String name) {System.out.println("hello component "+name);}
}
@Configuration // 将对象存储到Spring中
public class UserConfiguration {public void printConfiguration(String name) {System.out.println("hello Configuration "+name);}
}
@Bean方法注解,可以把方法返回的对象注入到Spring中
public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");// 得到 controller 对象UserController controller = applicationContext.getBean("userController",UserController.class);controller.printController("控制器");// 得到 service 对象UserService service = applicationContext.getBean("userService",UserService.class);service.printService("业务逻辑");// 得到 repository对象UserRepository repository = applicationContext.getBean("userRepository",UserRepository.class);repository.printRepository("数据持久DAO");// 得到 configurationUserConfiguration configuration = applicationContext.getBean("userConfiguration",UserConfiguration.class);configuration.printConfiguration("配置类");// 得到 componentUserComponent component = applicationContext.getBean("userComponent",UserComponent.class);component.printComponent("组件类");}
注意事项:Spring 默认情况下是类扫描,因此如果使用的是方法注解 @Bean,那么必须要配合类注解(@Component)一起使用(也可以是其它注解),才能将方法返回对象顺利存储到 Spring中
@Component
public class UserBean {@Beanpublic User user() {//伪代码//查询数据库获取对象User user = new User();user.setId(1);user.setName("张三");user.setAge(20);return user;}
}
获取对象
public class App {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");//通过 @Bean注解获取对象User user = applicationContext.getBean("user",User.class);System.out.println(user);}
}
注意:如果给@Bean起别名后,就只能用别名来获取对象了
@Component
public class UserBean {@Bean(name = {"getUser"})public User user() {//伪代码//查询数据库获取对象User user = new User();user.setId(1);user.setName("张三");user.setAge(20);return user;}
}
获取对象
public class App {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");//通过 @Bean注解获取对象User user = applicationContext.getBean("getUser",User.class);System.out.println(user);}
}
@Bean还可以起多个别名
@Component
public class UserBean {@Bean(name = {"getUser","myUser"})public User user() {//伪代码//查询数据库获取对象User user = new User();user.setId(1);user.setName("张三");user.setAge(20);return user;}}
并且 nume = 可以省略
@Bean({"getUser","myUser"})public User user() {//伪代码//查询数据库获取对象User user = new User();user.setId(1);user.setName("张三");user.setAge(20);return user;}
为啥要有那么多注解,就是让程序员看到类注解之后,就能直接了解当前类的⽤途
通过源码可以发现,@controller/@Service/@Repository/@Configuration
这四个注解从业务逻辑来说,可以认为这四个注解是 @Component的子类
查看 AnnotationBeanNameGenerator 中的源码
AnnotationBeanNameGenerator -> buildDefaultBeanName -> Introspector.decapitalize(shortClassName)
如果类名的长度大于1,并且第一个和第二个字母都是大写就直接返回
否则就把类名的第一个字母改为小写直接返回
从Spring中获取对象的手段:
@Service //将当前对象存储到 Spring 当中
public class UserService {/*** 通过用户Id查询用户* @param id* @return*/public User findUserById(int id) {// 伪查询,不连接sqlUser user = new User();if (id == 1) {user.setId(1);user.setName("张三");user.setAge(18);} else {user.setId(2);user.setName("李四");user.setAge(20);}return user;}
}
属性注⼊是使⽤ @Autowired 实现的,将 UserService 类注⼊到 Controller 类中
@Controller // 将当前的类存储到 Spring 中
public class UserController {// 属性注入(属性注册), 从Spring中取出对象,注入到当前类中@Autowiredprivate UserService userService;public User findUserById(Integer id) {if (id == null) {// 如果是无效参数return new User();}return userService.findUserById(id);}
}
注意:必须在 Setter方法上加上 @Autowired 注解,不然会注入失败。又因为spring是类扫描的,所以要在当前类上加上对应注解,该对象才有可能存入 spring 中
@Controller
public class UserController2 {private UserService userService;public User findUserById(Integer id) {if (id == null) {return new User();}return userService.findUserById(id);}// Setter注入@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}
}
注意:如果类中只有一个构造方法,@Autowired注解可以省略
@Controller
public class UserController3 {private UserService userService;//通过构造方法注入,若果只是存在一个构造方法,那么@Autowired可以省略@Autowiredpublic UserController3(UserService userService) {this.userService = userService;}public UserController3(String name) {System.out.println(name);}public User findUserById(Integer id) {if (id == null) {//判断id合法return new User();}return userService.findUserById(id);}
}
三种方式的getBean实现
public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");// 方法1: 属性注入UserController userController = (UserController) context.getBean("userController");System.out.println(userController.findUserById(2));// 方法2: Setter注入UserController2 userController2 = context.getBean("userController2",UserController2.class);System.out.println(userController2.findUserById(1));// 方法3: 构造方法注入UserController3 userController3 = context.getBean("userController3",UserController3.class);System.out.println(userController3.findUserById(2));}
@Resource 和 @Autowired 注解的使用方式非常类似
@Controller
public class UserController4 {@Resourceprivate UserService userService;public User findUserById(Integer id) {if (id == null) {return new User();}return userService.findUserById(id);}
}
@Controller
public class UserController5 {private UserService userService;public User findUserById(Integer id) {if (id == null) {return new User();}return userService.findUserById(id);}@Resourcepublic void setUserService(UserService userService) {this.userService = userService;}
}
注意:@Resource不能通过构造方法注入对象
@Autowired 和 @Resource 它们都是做了两手准备,它们会先从 一种类型进行选择,比如先从名称(ByName)进行获取Bean对象,如果根据名称获取不到,此时根据另一种类型(ByType)获取(根据名称或者类型获取)
如果Bean对象只有一个的时候,注入对象名就无所谓了
问题来了:如果注入的名称是不存在的,并且类型有多个,那么注入就会失败
@Component
public class UserBean {@Beanpublic User getUser1() {User user = new User();user.setId(1);user.setName("张三");user.setAge(22);return user;}@Beanpublic User getUser2() {User user = new User();user.setId(2);user.setName("李四");user.setAge(20);return user;}
}
注入代码
@Service
public class UserService {@Resourceprivate User user;public User findUserById(int id) {User user = new User();if (id == 1) {user.setId(1);user.setName("张三");user.setAge(18);} else {user.setId(2);user.setName("李四");user.setAge(20);}return user;}
}
运行就会报错,因为这里名字不存在,并且有多个类型注入
同⼀类型多个 Bean 报错处理,可以为Bean重命名,再通过重命名的名字注入Bean对象
@Service
public class UserService {@Resource(name = "getUser1")private User user;public User findUserById(int id) {User user = new User();if (id == 1) {user.setId(1);user.setName("张三");user.setAge(18);} else {user.setId(2);user.setName("李四");user.setAge(20);}return user;}
}
2.使用注入注解配合@Qualifier
来进行解决
@Service
public class UserService {@Autowired@Qualifier(value = "getUser2")private User user;public User findUserById(int id) {User user = new User();if (id == 1) {user.setId(1);user.setName("张三");user.setAge(18);} else {user.setId(2);user.setName("李四");user.setAge(20);}return user;}
}
上一篇:MySQL学习笔记(总结)
下一篇:JUC(十)