配置一个config类,在config类中 设置所需配置的内容.
一、 bean对象 给容器中注册组件
1.需要加上 @Configuration 注解告诉spring这是一个配置类.
2.在方法中加上@Bean注解 告诉spring这是一个bean对象.
3.在bean注解中 可以为该对象赋值指定的名字 name="xxx" ,在不指定的情况下, beanName默认未方法名.
4.返回类型为所配置的java类.
// 配置类=配置文件
@Configuration // 告诉Spring这是一个配置类
public class MainConfig {
// 给容器中注册一个Bean; 类型为返回值的类型, id默认是用方法名作为id.
@Bean("person_LiSi")
public Person person(){
return new Person("李四",20);
}
}
二、componentScan 自动扫描并指定规则
1.在被configuration注解标识的java类中,再加一个componentScan注解,用来说明该注解要扫描所有的组件,value为扫描的范围。
2. 可以使用excludeFilters/includeFilters 来标识被排除的类型
注意:此处的过滤类型是Filter[] 因此需要给指定类型的内容。
· value : 指定要扫描的包
· excludeFilters = Filter[] , 指定扫描的时候按照说明规则排除哪些组件
// 配置类=配置文件
@Configuration // 告诉Spring这是一个配置类
//@ComponentScan(value = "com.liz")
@ComponentScan(value = "com.liz", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {
Controller.class, Service.class
})
})
public class MainConfig {
}
· includeFilters = Filter[] , 指定扫描的时候只需要包含哪些组件(需要跟useDefaultFilters设置为false进行配合)
@ComponentScan(value = "com.liz", includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {
Controller.class, Service.class
})
},useDefaultFilters = false)
public class MainConfig {
}
3.此外可以更改FilterType 来改变所指定的类型.
FilterType包括:
ANNOTATION: 指定的注解,@Controller/@Service/@Component/@Repository
ASSIGNABLE_TYPE: 指定类型,可以写某个具体的java类
ASPECTJ: 使用ASPECTJ表达式
REGEX: 正则表达式,包含
CUSTOM: 给定一个TypeFilter的实现类
三、用@Scope来设置作用范围
1. prototype: 多实例的, IOC容器启动完成后,容器创建完成后,再调用方法获取,每次获取都新建一个。
2. singleton: 单实例的(默认值), IOC容器启动会调用方法创建对象放到ioc容器中。
以后每次获取就是直接从容器(map.get)中拿。
3. request
4. session
四、@Lazy 懒加载
单实例bean: 默认在容器启动的时候创建对象。
懒加载:容器启动不创建对象,第一次使用(获取)Bean创建对象,并初始化。
五、@Conditional : 按照一定的条件进行判断,满足条件给容器中注册bean。
需要调用实现condition接口的类,重写matches接口。
在@Conditional({xxxx.class})实现对bean的条件判断
该注解可以标在方法和类上。控制一个类的是否加载。
六、给容器中注册组件:
1.包扫描+组件标注注解(@Controller、@Service、@Repository、@Component
2.@Bean 导入的第三方包里面的组件
3.@Import 快速给容器中导入一个组件—— 在config类上加@Import注解,参数写要导入的组件类对象。
4. ImportSelector : 返回需要导入的组件的全类名,通过实现和重写的方式来完成.
5. ImportBeanDefinitionRegistrar : 手动注册bean到容器
6. 使用Spring提供的FactoryBean
当getBean 方法中没有前缀"&" 时,spring会返回该FactoryBean的getObject的返回类型。但当有前缀“&”时,spring会解析到该&符号,并且返回该FactoryBean。
创建Bean的Factory——BeanFactory 中会:
Bean的生命周期:
bean创建----初始化-----销毁过程
容器管理bean的生命周期;
我们可以自定义初始化和销毁方法;容器在bean进行到当前的生命周期的时候来调用玩哦们自定义的初始化和销毁方法。
1.指定初始化和销毁方法:
通过bean 标签的 initMethod 属性和 destroyMethod 属性指定 对应bean所自定义的 init 和destroy 方法。
单实例 是在容器创建时初始化对象,并且在关闭的时候销毁对象,多实例是在获取对象的时候,初始化对象,没有销毁方法。
2. 通过让Bean实现InitializingBean(定义初始化逻辑)
实现 DisposableBean(定义销毁逻辑)
3. 使用JSR250
@PostConstruct 在bean创建完成并且属性赋值完成; 来执行初始化方法
@PreDestroy 在容器销毁bean之前通知我们进行清理工作
4. BeanPostProcessor[interface] bean 的后置处理器;
在bean初始化前后进行一些处理工作;
postProcessBeforeInitialization:
postProcessAfterInitialization
Bean的属性赋值
使用@Value赋值;
1.基本数值
2. 可以写SpEL; #{}
3. 可以写${} ; 取出配置文件中的值
步骤1:首先在config文件中用@PropertySource(value={"classpath:/person.properties"})读取配置文件到运行的环境变量中.
步骤2: 在bean中使用@Value(${person.nickName}) 获取配置文件中的属性值.
自动装配
spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值;
1. @Autowired
优先按照类型去容器中找对应的组件,如果找到多个,则再用属性的名称作为组件的id去容器中查找
但是使用@Qualifier("xxx") 可以直接指定需要装配的组件id,而不是使用属性名.
可以在autowired中把 required属性设置为false 这样该组件为非必须,即使找不到也不会报错
@Primary 加在组件上 , 意义是:让spring在自动装配的时候,即便是找到多个同类型组件,也首选装配加了@Primary注解的组件.
2.@Resource
3. 自定义组件要想使用Spring容器的一些底层组件(ApplicationContext, BeanFactory等)
需要用自定义组件实现XXXAware; 再创建对象的时候,会调用接口规定的方法注入相关组件,每个Aware都有对应的Processor,来处理需要调用的底层组件.
4. @Profile
可以根据当前的环境,动态的激活和切换一系列组件的功能.
1. 使用命令行动态参数: 在虚拟机参数位置加载-Dspring.profiles.active = xxx
2. 使用代码的方式
1.创建一个applicationContext(无参)
2. 设置需要激活的环境
3. 注册主配置类
4. 启动刷新容器
AOP
1.首先要导入aop模块:spring-aspects
2.定义一个切面类(LogAspects),切面里面的方法需要动态感知业务逻辑类方法的运行
通知方法:
前置通知(@Before) 在目标方法运行之前
后置通知(@After)
返回通知(@AfterReturning)
异常通知(@AfterThrowing)
环绕通知(@Arount)
使用@Pointcut 来完成抽取公共的切入点表达式
3.在切面类上加注解@Aspect 来告诉spring这是一个切面类 同时该切面类也需要注册到spring容器中.
4!: 给配置类中加 @EnableAspectJAutoProxy【开启基于注解的aop模式】
% 如果想要切面程序生效需要拿到spring容器中的组件而不是自己创建的bean
5. 通过JoinPoint 获得切入点的名称、参数等信息
异常和返回结果的信息需要在注解中声明变量名称
AOP原理
1.@EnableAspectJAutoProxy
AOP拦截器链的触发过程:
1. 如果没有拦截器直接执行目标方法,后者拦截器的索引和拦截器的数组大小-1一样(到了最后一个拦截器)。
2. 链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行。
拦截器链的机制保证通知方法与目标方法的执行顺序。
具体流程: 开启---注册---创建---执行
AOP总结:
1. 使用@EnableAspectJAutoProxy 开启AOP功能
2. @EnableAspectJAutoProxy 会给容器注册一个组件 AnnotationAwareAspectJAutoProxyCreator
3. AnnotationAwareAspectJAutoProxyCreator 是一个后置处理器
4. 容器的创建流程:
1. registerBeanPostProcessors() 注册后置处理器 ; 创建AnnotationAwareAspectJAutoProxyCreator 对象.
2. finishBeanFactoryInitialization() 初始化剩下的单实例bean
1. 创建业务逻辑组件和切面组件
2. AnnotationAwareAspectJAutoProxyCreator 拦截组件的创建过程
3. 组件创建完之后, 判断组件是否需要增强(加入aop的通知)
如果是: 切面的通知方法, 包装成增强器(Advisor) ; 给业务逻辑组件创建一个代理对象.
5. 执行目标方法:
1. 代理对象执行目标方法
2. CglibAopProxy.intercept() :
1. 得到目标方法的拦截器链( 增强器包装成拦截器MethodInterceptor )
2. 利用拦截器的链式机制 依次进入每一个拦截器进行执行;
3. 效果:
正常执行: 前置通知 => 目标方法 => 后置通知 => 返回通知
异常执行: 前置通知 => 目标方法 => 后置通知 => 异常通知