接着上一篇
4.Bean 的作用域
4.1单例模式singleton
(spring 默认机制)
<bean id="user2" class="com.huliyong.domain.User" scope="singleton"/>
您定义一个bean定义并且其作用域为单例时,Spring IoC容器将为该bean定义所定义的对象创建一个实例。该单个实例存储在此类单例bean的高速缓存中,并且对该命名bean的所有后续请求和引用都返回该高速缓存的对象。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Udg2kBkv-1591629651177)(C:\Users\hly\AppData\Roaming\Typora\typora-user-images\image-20200607163857094.png)]
4.2原型模式prototype
每次从容器中get 的时候 都会产生一个新的对象
<bean id="user2" class="com.huliyong.domain.User" scope="prototype"/>
4.3 web 中
request session application 在web 开发中用到
Bean 的自动装配
- 是Spring 满足bean 依赖的一种方式
- Spring 在上下文中自动寻找 并给bean 装配属性
Spring的三种装配方式
- 在xml 中显示的装配
- java中显示配置
- 隐式的自动装配bean
环境配置
: 一个people 拥有cat and dog
原模式
<bean id="Dog" class="com.huliyong.domain.dog"/>
<bean id="Cat" class="com.huliyong.domain.cat"/>
<bean id="people" class="com.huliyong.domain.peoPle" >
<property name="name" value="hu"/>
<property name="cat" ref="Cat"/>
<property name="dog" ref="Dog"/>
</bean>
autowire 自动装配
byName :
自动在容器的上下文中查找 和自己对象set 后面跟着的值对应的id (属性名)
setDog() 就是查找dog(小写)
<bean id="dog" class="com.huliyong.domain.dog"/>
<bean id="dat" class="com.huliyong.domain.cat"/>
<bean id="people" class="com.huliyong.domain.peoPle" autowire="byName">
<property name="name" value="hu"/>
</bean>
byType
自动在容器的上下文中查找 和自己对象属性类型相同的bean
<bean class="com.huliyong.domain.dog"/>
<bean class="com.huliyong.domain.cat"/>
<bean id="people" class="com.huliyong.domain.peoPle" autowire="byType">
<property name="name" value="hu"/>
</bean>
<bean class="com.huliyong.domain.dog"/>
<bean class="com.huliyong.domain.cat"/>
<bean id="people" class="com.huliyong.domain.peoPle" autowire="byType">
<property name="name" value="hu"/>
</bean>
总结
- byname 的时候 要保证bean id 唯一 并且这个bean 需要和自动注入的属性的set 方法的值一致
- byType 的时候 要保证所有的bean 的class 唯一 并且这个bean 需要和自动注入的属性类型一致
使用注解进行自动装配
注解与xml 各有各的好处
使用注解需知
- 导入约束
- 配置注解支持
idea 中可直接输入< context:annotation-config> 自动导入约束
<?xml version="1.0" encoding="UTF-8"?>
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
@Autowired
- 可以加在属性上面 也可以加在set 方法上面 也可以放在任意方法上表示,自动执行当前方法,如果方法有参数,会在IOC容器中自动寻找同类型参数为其传值。
使用Autowired 可以不写set 方法前提是自动装配的属性在IOC容器里面存在 且符合byType
如果@Autowired自动装配的环境比较复杂,自动装配无法通过-一个注解[@Autowired] 完成的时候、我们可以使用@Qualifier(value=“xx”)去配置@Autowired的使用,指定一个唯一-的bean对象注入!
注意事项:
在使用@Autowired时,首先在容器中查询对应类型的bean
如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据
如果查询的结果不止一个,那么@Autowired会根据名称来查找。
如果查询的结果为空,那么会抛出异常。解决方法时,使用required=false
1、强制性
默认,它具有强制契约特性,其所标注的属性必须是可装配的。如果没有Bean可以装配到Autowired所标注的属性或参数中,那么你会看到NoSuchBeanDefinitionException
的异常信息。
不确定属性是否可以装配,可以这样来使用Autowired。
@Autowired(required=false)
private Dog dog;
3、优先级
通过byType可能会找到多个实例的Bean。然后再通过byName来确定一个合适的Bean,如果通过名称也确定不了
determineAutowireCandidate方法来确定
- 通过@Primary注解来标识Bean
- 通过@Priority(value = 0)注解来标识Bean value为优先级大小
@Resourse
pub1ic class People {
@Resource(name = "cat2")
private Cat cat;
@Resource
private Dog dog;
}
@Resourse 与@Autowired 的区别
@Autowired为Spring提供的注解
@Autowired默认策略为byType 注入
public class UserService {
@Autowired
private UserDao userDao;
}
这样装配回去spring容器中找到类型为UserDao的类,然后将其注入进来。这样会产生一个问题,当一个类型有多个bean值的时候,会造成无法选择具体注入哪一个的情况,这个时候我们需要配合着@Qualifier使用。
public class UserService {
@Autowired
@Qualifier(name="userDao1")
private UserDao userDao;
}
@Resource注解由Jdk提供
@Resource默认按照ByName自动注入
public class UserService {
@Resource
private UserDao userDao;
@Resource(name="studentDao")
private StudentDao studentDao;
@Resource(type="TeacherDao")
private TeacherDao teacherDao;
@Resource(name="manDao",type="ManDao")
private ManDao manDao;
}
①如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
②如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
③如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
④如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。
两者都可以写在字段和setter方法上。两者如果都写在字段上,那么就不需要再写setter方法
使用注解开发
bean
spring4之后使用注解开发 保证aop 包导入了
导入< context:annotation-config> 约束
这个会自动扫描指定的包 这个包下面的注解就会生效
<context:component-scan base-package="com.huliyong.domain"/>
@Component :组件 放在类上 就说明这个类被Spring 管理了 就是bean
属性注入
@Component
public class User {
public String name ;
@Value("hulll22")
public void setName(String name) {
this.name = name;
}
}
上面加上@Value(“hu”) 相对于
<bean id="user" class="com.huliyong.domain.User">
<property name="name" value="hu"/>
</bean>
衍生的注解
@Component 有衍生注解 web 开发中按照三层架构分层
-
dao [@Repository]
-
service [@Service]
-
controller [@Controller
他们的功能都是相同的 都代表把类注册到spring中 装配bean
作用域
在类上面加@Scope()
@Scope(“singleton”) 单例
“prototype“
xml 与注解
xml 更加万能 适用于任何 场合 维护简单
注解不是自己的类 使用不了 维护相对复杂
xml 与注解相对好的实践
xml 用来管理bean
注解负责完成属性的注入
使用注解中要注意 开启注解支持
< context:annotation-config>
<context:component-scan base-package="com.huliyong.domain"/>
使用Java的方法配置注解
现在不需要使用Spring 的xml 配置 全部交给java 来做
springConfig (springboot中很常见)
@Configuration
public class huConfig {
@Bean //注册一个bean
public User user(){
return new User();
}
}
等效于
<beans>
<bean id="user" class="com.huliyong.domain"/>
</beans>
测试
@Test
public void test(){
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(huConfig.class);
Object user = applicationContext.getBean("user");
System.out.println(user.toString());
}
输出 User{name=‘hu’}
@Configuration
@ComponentScan("com.huliyong.domain") //扫描这个包 下// 有@Component
public class huConfig {
//@Bean
public User user(){
return new User();
}
}
@Component
public class User {
public String name;
public String getName() {
return name;
}
@Value("hu")
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
@Configuration
这个会Spring容器托管,注册到容器中,因为他本米就是一 个@Component, @Configuration代表这是一 个配置类
合并:
与前面的applicationContext.xml 一样 有很多的config 但是都可导入到一个config 中 使用@Import(config2.class)