目的:
当我们还在使用Spring、SpringMVC、Mybatis三大框架来整合开发的时候,我们会写大量的xml文件来进行配置;然而在Springboot和SpringCloud兴起之后,学习Spring的注解驱动及其原理那将会是非常有必要的了;因为在Springboot和SpringCloud里面会使用到大量的注解来进行配置;当我们熟练掌握了Spring的注解驱动,那当我们在学习Springboot和SpringCloud框架的时候,那将会更加的轻松自如。
// 配置类
@Configuration
public class MainConfig {
@Bean
public Person person01() {
return new Person("1", "wangwu", 12);
}
}
测试:
public class MyTest {
@Test
public void test01() {
// 使用注解
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
Person person = (Person) annotationConfigApplicationContext.getBean("person");
System.out.println(person);
// String[] beanNamesForType = annotationConfigApplicationContext.getBeanNamesForType(Person.class);
// for (String beanname : beanNamesForType) {
// System.out.println(beanname);
// }
}
}
// 配置类
@Configuration
// 扫描com.yajun.spring01包下标注了@Controller @Service @Repository @Component注解的类,加载到容器中
@ComponentScan(value = "com.yajun.spring01")
public class MainConfig {
@Bean
public Person person01() {
return new Person("1", "wangwu", 12);
}
}
包扫描排除:
解释:包扫描排除按照注解类型排除,排除标注@Controller和@Service注解的类,不加入容器
excludeFilters = Filter[]
@ComponentScan(value = “com.yajun.spring01”, excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class,Service.class})
})
prototype:多实例的
singleton:单实例的(默认值)
request:同一次请求创建一个实例(比较少用)
session:同一个session创建一个实例(比较少用)
// 配置类
@Configuration
@ComponentScan(value = "com.yajun.spring01", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class})
})
public class MainConfig {
@Bean
@Scope(value = "prototype") // 多实例的 调用的时候创建对象
public Person person() {
return new Person("1", "wangwu", 12);
}
}
懒加载:容器启动不创建对象,第一次使用(获取 )的时候创建
按照一定的条件进行判断,满足条件给容器注册bean(可以定义在方法或者类上面)
public class WindosCondition implements Condition {
// 判断系统的操作类型
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
BeanDefinitionRegistry registry = conditionContext.getRegistry();
String[] beanDefinitionNames = registry.getBeanDefinitionNames();
System.out.println("条件开始执行");
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("os.name");
if (property.contains("Windows")) {
return true;
}
return false;
}
}
配置类:
// 配置类
@Configuration
@ComponentScan(value = "com.yajun.spring01", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class})
})
public class MainConfig {
@Bean
// @Scope(value = "prototype")
// @Conditional(WindosCondition.class)
public Person person() {
return new Person("1", "wangwu", 12);
}
@Bean
@Conditional(WindosCondition.class) // 实现了Contidion接口的类
public Person person01() {
return new Person("2", "张三", 14);
}
@Bean
@Conditional(WindosCondition.class)
public Person person02() {
return new Person("5", "李四", 15);
}
}
直接导入类:
@Import(Bule.class)
public class MainConfig {
}
导入实现了ImportSelector接口的类,实现方法返回一个类名数组:
public class MyImportSelectot implements ImportSelector {
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{"com.yajun.spring01.bean.Red","com.yajun.spring01.bean.Yellow"};
}
}
配置类:
@Import({Bule.class, MyImportSelectot.class})
public class MainConfig {
}
导入实现了ImportBeanDefinitionRegistrar接口的类
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
BeanDefinition beanDefinition = beanDefinitionRegistry.getBeanDefinition("com.yajun.spring01.bean.Red");
String beanClassName = beanDefinition.getBeanClassName();
System.out.println(beanClassName);
boolean b = beanDefinitionRegistry.containsBeanDefinition("com.yajun.spring01.bean.Red");
// 如果容器红有Red对象就把Green也注册到容器中
if (b) {
BeanDefinition beanDefinition1 = new RootBeanDefinition(Green.class);
beanDefinitionRegistry.registerBeanDefinition("green",beanDefinition1);
}
}
}
配置类
// 用@Import注解把上面的类加载进来
@Import({Bule.class, MyImportSelectot.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig {
}
import org.springframework.beans.factory.FactoryBean;
public class ColorFactoryBean implements FactoryBean<Color> {
public Color getObject() throws Exception {
System.out.println("new Color()...");
return new Color();
}
public Class<?> getObjectType() {
return Color.class;
}
public boolean isSingleton() {
return true;
}
}
@Bean
public ColorFactoryBean colorFactoryBean() {
return new ColorFactoryBean();
}
}
测试结果:
public class MyTest {
@Test
public void test01() {
// 使用注解
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
Object colorFactoryBean = annotationConfigApplicationContext.getBean("colorFactoryBean");
System.out.println(colorFactoryBean.getClass());
}
}
结果:
class com.yajun.spring01.bean.Color
分析:往容器中实际导入的是工厂bean,实际注册的Color对象
如果要拿到ColorFactoryBean本省,获取的时候在名字前面加&符号:
列:Object colorFactoryBean = annotationConfigApplicationContext.getBean("&colorFactoryBean")
包扫描(ComponentScan) + 组件标注注解(@Controller/ @Service/ @Repository/ @Component)【自己写的】
@Bean【导入第三方包里面的组件】
@Import【快速的给容器中导入一个组件】
- @Import(要导入到容器的组件),容器就会自动注册这个组件,id是默认是 全类名
- ImportSelector(定义一个类实现ImportSelector): 返回需要导入组件的全类名数组;
- ImportBeanDefinitionRegistrar(定义一个类实现ImportBeanDefinitionRegistrar):手动注册 bean到容器中
使用Spring提供的FactoryBean(工厂bean)
指定初始化和销毁方法:指定init-method和destory-method
bean:
public class Car {
public void init() {
System.out.println("Car...init...");
}
public void destory() {
System.out.println("Car...destory...");
}
}
配置类:
@Configuration
public class MyConfig02 {
@Bean(initMethod = "init",destroyMethod = "destory")
public Car car() {
return new Car();
}
}
测试:
public class MyTest01 {
@Test
public void test01() {
// 初始化容器
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MyConfig02.class);
System.out.println("容器启动完成...");
annotationConfigApplicationContext.close();
}
}
结果:容器启动的时候,执行了car的init方法,容器关闭的时候执行destory方法
Car...init...
容器启动完成...
Car...destory...