目录
使用@Scope和@Lazy调整被Spring管理的对象的作用域;
使用@Autowired和@Resource这2个注解实现自动装配时的区别:
通过Spring框架读取.properties配置文件中的信息:
@Resource:由JSR-250提供(等同于@Autowired)
Spring
【掌握】
Spring框架的主要作用:
创建对象,管理对象;
Spring框架深层的作用:
解耦;Spring提供的IOC和AOP功能,可以将组件的耦合度降至最低,即解耦,便于系统日后的维护和升级;
通过Spring框架创建对象
在某个类中自定义方法,方法的返回值类型就是需要Spring框架创建对象的类型,在方法体中自行返回所需要创建的对象,并且为方法添加@Bean
注解,后续,只要Spring框架加载这个类,就会自动调用被添加了@Bean
注解的方法,并管理方法所返回的对象。通常,当需要管理的对象所归属的类不是自定义的,必须使用这种做法;
使得Spring框架执行组件扫描,保证相关的类在组件扫描的包或其子孙包中,并且,类还需要添加@Component
/ @Controller
/ @Service
/ @Repository
注解中的某1个。通常,当需要管理的对象所归属的类是自定义的,优先使用这种做法。
关于组件扫描:
可以将组件扫描的包名称作为字符串参数直接应用于AnnotationConfigApplicationContext
类的构造方法中,但是,并不推荐使用这种做法,在实际项目开发时,AnnotationConfigApplicationContext
类通常不是开发人员自行创建的,也就没有办法在构造方法中添加包的名称!推荐使用自定义的类作为配置类,并结合@ComponentScan
注解来配置组件扫描;
被Spring管理的对象默认是单例的
(注意:Spring框架不是设计模式中的单例模式,只是管理对象的方法是这样的),并且,不是懒加载的模式(相当于单例即墨市中的饿汉式单例的效果):
【理解】
使用@Scope
和@Lazy
调整被Spring管理的对象的作用域;
被Spring管理的对象的生命周期;
配置对象的生命周期:
-
如果使用的是添加了
@Bean
注解的自定义方法返回对象的做法,在@Bean
注解中配置initMethod
和destroyMethod
属性,就可以将类中的方法分别指定为初始化方法和销毁方法; -
如果使用的是组件扫描和组件注解的做法,在类中的初始化方法之前添加
@PostConstruct
注解,在销毁方法之前添加@PreDestroy
方法。
关于Spring框架的DI与IOC:
-
DI:Dependency Injection,依赖注入,具体的表现就是“为当前类对象所依赖的某个属性注入值”;
-
IOC:Inversion of Control:控制反转,在传统模式下,是由开发人员自行创建对象(例如
User user = new User();
)且管理对象(例如user.setName("Jack");
),可以理解为开发人员具有对象的控制权,当使用了Spring框架后,创建对象和管理对象的权力就交给了框架。 -
在Spring框架中,DI是一种做法,IoC是最终实现的效果,也就是“Spring框架通过DI这种做法实现了IoC的效果”。
Spring框架自动装配机制的2种装配模式:
-
byName
:根据名称实现自动装配,在这种模式下,要求被装配的属性名称,与被Spring管理的对象的名称(调用getBean()
方法给出的参数名)必须相同; -
byType
:根据类型实现自动装配,在这种模式,要求被装配的属性的类型,在Spring容器中存在匹配类型的对象,当应用这种机制时,必须在Spring容器中保证匹配类型的对象只有1个,否则,将会出现NoUniqueBeanDefinitionException
异常;
使用@Autowired
和@Resource
这2个注解实现自动装配时的区别:
-
使用
@Autowired
尝试自动装配时,Spring框架会先根据byType
模式找出所有匹配类型的对象,如果匹配类型的对象的数量为0,也就是没有匹配类型的对象,默认情况下会直接报错(如果明确的配置为@Autowired(required=false)
时不会因为装配失败而出错);如果匹配类型的对象的数量为1,则直接装配;如果匹配类型的对象的数量超过1个(有2个甚至更多个),会尝试byName
来装配,如果存在名称匹配的对象,则成功装配,如果名称均不匹配,则装配失败。 -
使用
@Resource
注解尝试自动装配时,其工作原理是先尝试byName
装配,如果存在名称匹配的对象,则直接装配,如果没有名称匹配的对象,则尝试byType
装配。
通过Spring框架读取.properties配置文件中的信息:
-
在组件类的声明之前添加
@PropertySource
注解,以配置需要读取的.properties文件的位置,然后,通过@Value
注解将读取到的属性值一一注入到类的属性中,在声明类的属性时,只要该属性的类型是常规类型(例如基本数据类型、String
等)或Spring框架自定义的类型,都可以将类的属性直接声明为所期望的类型; -
在组件类的声明之前添加
@PropertySource
注解,以配置需要读取的.properties文件的位置,然后,在类中自定义Environment
接口类型的对象,通过@Autowired
为该对象自动装配值,后续,调用该对象的getProperty()
方法即可获取在.properties文件中配置的属性值。
Spring常用注解
@Bean
产生一个bean的方法,并且交给Spring容器管理,
声明bean的注解
@Controller, @Service, @Repository,@Component目前4种注解意思是一样,并没有什么区别,区别只是名字不同。
@Component 组件,没有明确的角色
把普通pojo实例化到spring容器中,相当于配置文件中的 <bean id="" class=""/>
它泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),我们就可以使用@Component来标注这个类。
调用无参构造创建一个bean对象,并把对象存入spring的IOC容器,交由spring容器进行管理。相当于在xml中配置一个bean。
此外,被@controller 、@service、@repository 、@component 注解的类,都会把这些类纳入进spring容器中进行管理
@Service 在业务逻辑层使用(service层)
用于标注业务层组件,以注解的方式把这个类注入到spring配置中
@Repository 在数据访问层使用(dao层)
一般用于持久层的注解。作用为给bean在容器中命名
@Controller 在展现层使用,控制器的声明(C)
标识一个该类是Spring MVC controller处理器,用来创建处理http请求的对象.
依赖注入与自动装配
依赖注入的本质就是装配,装配是依赖注入的具体行为。
@Autowired:由Spring提供
- Autowired默认先按byType,如果发现找到多个bean,则,又按照byName方式比对,如果还有多个,则报出异常。
- 如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false)
- required属性决定依赖注入是否必选,缺省true,意味着没有合适类型bean注入时,会抛出异常。
@Resource:由JSR-250提供(等同于@Autowired)
javax的注解,实现自动注入,优先byName(缺省以字段名称或入参名称做搜索),其次byType。
@Autowired按byType自动注入,而@Resource默认按 byName自动注入,@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
@Value
- 通过@Value可以将外部的值动态注入到Bean中,可以为基本类型数据和String类型数据的变量注入数据
- 为了简化从properties里取配置,可以使用@Value, 可以properties文件中的配置值。在dispatcher-servlet.xml里引入properties文件。
java配置类相关注解
@ComponentScan
- 作用在类上,声明需要对包路径下资源进行扫描,效果等同于<context:component-scan>
- value(basePackages) 属性指定要扫描的包路径,多个用逗号分割。
用于改变bean作用范围的注解
@Scope
指定bean的作用范围。@Scope注解是springIoc容器中的一个作用域,在 Spring IoC 容器中具有以下几种作用域:基本作用域singleton(单例)、prototype(多例),Web 作用域(reqeust、session、globalsession),自定义作用域。(@Scope注解默认的singleton单例模式)
属性:
value:
1)singleton:单例
2)prototype:多例
3)request:
4)session:
5)globalsession:
案例:
@Autowire
@Scope(value="prototype")
private UserService userService;
生命周期相关的注解
@PostConstruct
在构造方法和init方法(如果有的话)之间得到调用,且只会执行一次。javax的注解,修饰方法,此方法会在依赖注入后回调。
@PreDestory
注解的方法在destory()方法调用后得到执行。javax的注解,修饰方法,在对象从容器移除之前回调。
实现初始化和销毁Bean之前的操作,只能有一个方法可以用此注释进行注释,方法不能有参数,返回值必需是void,方法需要是非静态的。
public class Demo{
@PostConstruct
public void init(){
System.out.println("初始化");
}
@PreDestroy
public void dostory(){
System.out.println("销毁");
}
}
@Lazy
修改饿汉式为懒汉式
Lazy注解作用于很广,能和很多注解配合使用,用于标记是否延迟加载。
用于指定该Bean是否取消预初始化,用于注解类,延迟初始化。
value属性默认是true,也即带上@Lazy注解后默认就是延迟加载。
@PropertySource
作用在类上,加载指定路径资源到Environment,从而实现注入。
然后,在类的声明之前,通过`@PropertySource`配置需要读取的配置文件:
@PropertySource("classpath:jdbc.properties")