# 一、核心容器
【1】@Configuration
:告诉 Spring 这是一个配置类(配置类=配置文件)
【2】@Bean
:给容器中注册一个Bean
;类型为返回值类型,id 默认是用方法名作为 id 也可以通过 value 属性添加 id(相当于 xml 中的<bean>
标签),主要用于导入第三方包里面的组件。
【3】@ComponentScan
:包扫描,只要标注了 @Cotroller
、@Service
、@Repository
、@Componet
等注解便会自动注入此类,excludeFilters
属性可以定义需要排除的注解或者类,通过@Filter
数组进行定义,type
属性为类型(注解、类、正则、自定义的TypeFilter
等等)class
为排除的类或注解类。includeFilters
属性指定只需要扫描包含的注解或者类,但需要关闭默认的扫描包注解的规则:useDefaultFilters=false
默认为true
。主要用于导入自己定义的组件。
@Configuration
@ComponentScan(value="com.atyintong"/*,excludeFilters= {
@Filter(type=FilterType.ANNOTATION,classes={Controller.class,Service.class})
},useDefaultFilters=false,includeFilters= {
@Filter(type=FilterType.ANNOTATION,classes=Service.class)
}*/)
public class MainConfig {
@Bean
public Person persion() {
return new Person("zzx",12);
}
}
2
3
4
5
6
7
8
9
10
11
12
【4】获取配置文件的方式:new AnnotationConfigApplicationContext(MainConfig.class)
AnnotationConfigApplicationContext application=new AnnotationConfigApplicationContext(MainConfig.class);
@Test
public void test() {
Person person = application.getBean(Person.class);
System.out.println(person);
}
/*输入内容如下:Person [name=zzx, age=12, nickName=null]*/
2
3
4
5
6
7
【5】@scope
:默认为singleton
表示单实例,容器启动时调用方法创建对象放到ioc
容器中,以后每次调用时直接从中获取。常用的还有prototype
表示多实例,容器启动时不创建对象,每当调用时才创建当前对象。
@Scope(value="prototype")
@Bean
public Person persion() {
2
3
【6】@lazy
:懒加载,单实例bean
默认在容器启动时不创建对象,第一次获取对象的时候创建对象。以后调用不再创建对象。
【7】@Conditonal({Condition})
:按照一定条件进行判断,放在配置类的方法上表示,满足条件才给容器注册bean
。也可以放在类上表示,满足条件才执行配置类。首先需要自定义一个实现Condition
接口的类,如下:
public class TestCondition implements Condition{
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 1、context:判断条件能使用的上下文环境
// 2、metadata:注释信息
// 1.1 获取当前环境信息
Environment environment = context.getEnvironment();
// 1.2 获取bean的注册类信息
BeanDefinitionRegistry registry = context.getRegistry();
String property = environment.getProperty("os.name");
if(property.contains("Windows") && !registry.containsBeanDefinition("person")) {
return true;
}
return false;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
在配置内中加载两个不同的Persion
对象,并在person01
对象加载方法前加入@Conditional
注解,查看是否加载此对象。
@Bean
public Person person() {
return new Person("zzx",12);
}
@Conditional(TestCondition.class)
@Bean("person01")
public Person person01() {
return new Person("lisi",13);
}
/* IOC 容器启动时,不包含person01 对象,因为Conditional 条件返回为 false */
2
3
4
5
6
7
8
9
10
11
【8】@Import
:导入组件,id
默认是组件的全类名。
@Import({Cat.class,MyImportSelector.class}) //输出的结果为:com.atyintong.bean.Cat
@Configuration
public class MainConfig {
2
3
也可以将需要导入的组件集合定义在一个继承了ImportSelector
的类中,并将此类通过@Import
注解导入到容器中,如下:
public class MyImportSelector implements ImportSelector{
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 通过全类名,导入需要的组件
return new String[] {"com.atyintong.bean.Color"};
}
}
2
3
4
5
6
7
8
【9】@FactoryBean
:使用Spring
提供的FactoryBean
。默认获取到的是工厂bean
调用getObject()
创建的对象,而要获取工厂Bean
本身需要给id
前面加一个&
标识。如下:
/**
* @ClassName: CarFactoryBean
* @Description: 实现 FactoryBean 接口,并在泛型中传入需要实例化的类
* @author: zzx
* @date: 2019年1月13日 下午11:12:45
*/
public class CarFactoryBean implements FactoryBean<Car> {
@Override
public Car getObject() throws Exception {
// 创建泛型中的对象,对象会添加到容器中
return new Car();
}
@Override
public Class<?> getObjectType() {
// 对象的类型
return Car.class;
}
@Override
public boolean isSingleton() {
// true 表示对象是单例,false 表示多实例
return true;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
对上述理论的测试:
@Test
public void testFactory() {
Object car0 = application.getBean("carFactoryBean");
Object car1 = application.getBean("carFactoryBean");
Object car2 = application.getBean("&carFactoryBean");
//输入为 true,因为是单实例
System.out.println(car0 == car1);
//输出:com.atyintong.bean.Car@3d299e3
System.out.println(car1);
//输出:com.atyintong.condition.CarFactoryBean@55a561cf
System.out.println(car2);
}
2
3
4
5
6
7
8
9
10
11
12
# 二、Bean 的声明周期
【1】bean
指定初始化和销毁方法:通过指定initMethod
属性指定初始化方法,destroyMethod
属性指定销毁方法。其中init
和destroy
方法是Car
对象中定义的方法。
@Bean(initMethod="init",destroyMethod="destory")
public Car car() {
return new Car();
}
2
3
4
【2】类通过实现InitializingBean
、DisposableBean
接口
public class Cat implements InitializingBean,DisposableBean{
@Override
public void destroy() throws Exception {
// 定义销毁逻辑
}
@Override
public void afterPropertiesSet() throws Exception {
// 定义初始化逻辑
}
}
2
3
4
5
6
7
8
9
10
11
12
【3】@PostConstruct
:对象创建并赋值之后调用,@PreDestory
:容器移除对象之前。
public class Color {
//对象创建并赋值之后调用
@PostConstruct
public void init() {
}
//容器移除对象之前
@PreDestroy
public void destory() {
}
}
2
3
4
5
6
7
8
9
10
11
12
【4】后置处理器:BeanPostProcessor
在类的init
方法前执行postProcessBeforeInitialization
方法中任务,在初始化init
之后执行postProcessAfterInitialization
方法。
@Component
public class MyBeanPostProcess implements BeanPostProcessor{
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//bean 表示当前类的全类名,beanName 表示容器中的 id
/* 测试输入:构造函数。。。
com.atyintong.bean.Car@1b083826---->car
init 初始化方法,创建对象之前
com.atyintong.bean.Car@1b083826---->car */
System.out.println(bean+"---->"+beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(bean+"---->"+beanName);
return bean;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 三、组件赋值
【1】@Value()
:进行属性赋值操作
public class Person {
//使用@Value赋值;
//1、基本数值
//2、可以写SpEL; #{}
//3、可以写${};取出配置文件【properties】中的值(在运行环境变量里面的值)
@Value("${person.name}")
private String name;
2
3
4
5
6
7
8
【2】@PropertySource()
:引入配置文件时使用,通过${key}
获取配置内容
@PropertySource(value= {"classpath:/Persion.properties"})
public class MainConfig {
2
【3】@Autowired()
:自动注入,默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class)
,如果找到多个相同类型的组件,再将属性的名称作为组件id
去容器中查找。但可以使用@Qualifier("xxx")
指定需要装配的组件的 id
,而不使用属性名。自动装备一定要将属性赋值号,如果没有在容器中找到此属性,就会报notfoundxxx
错误,或者指定自动加载的required
属性为false
,就不必须加载此类也不用报错。
@Service
public class BookService {
@Qualifier("bookDao1")
@Autowired(required=false)
private BookDao bookDao;
2
3
4
5
当容器中存在多个同类对象时,我可以某个上添加@primary
注解,当自动注入时,就会优先注入。
@Primary
@Bean("person01")
public Person person01() {
2
3
【4】@Resource
:与@Autowired
一样实现自动装配功能,默认是按照组件名称进行装配。不支持@primary
注解和required
属性。
@Resource(name="bookDao")
private BookDao bookDao;
2
【5】@Inject
:需要导入javax.inject
包,和@Autowired
功能一样,但其没有required
属性。@Autowired
:Spring
定义的,@Resource
、@Inject
都是java
规范。
@Inject
private BookDao bookDao;
2