1. 环境配置
1.1 使用Maven进行测试
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
2. Xml装配
2.1 新建aplicationContext.xml
文件
<beans>
<bean id="person" class="entity.Person">
<property name="name" value="lisi"/>
<property name="age" value="10"/>
</bean>
<bean id="constructorPerson" class="entity.Person">
<constructor-arg name="name" value="zhangsan"/>
<constructor-arg name="age" value="20"/>
</bean>
</beans>
2.2 新建person
对象
public class Person {
private String name;
private int age;
//省略setter和getter+有参构造函数
}
2.3 新建测试类
public class PersonTest extends TestCase {
@Test
public void testBean() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) applicationContext.getBean("person");
System.out.println(person);
}
@Test
public void testPerson() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
}
}
2.4 测试结果:
Person(name=lisi, age=10)
person
constructorPerson
2.5 结果分析:
不管是使用property还是使用构造参数传入值,都可以进行对象的获取
3. 配置类
3.1 使用Java代码进行配置,需要用到的注解@Configuration
3.2 新建配置类:@Configuration
表示这是一个注解@Bean
表示这是一个需要装配的对象,具体表现为bean文件,可以参考使用xml进行配置中的第一个对象的装配
@Configuration
public class BeanConfiguration {
@Bean
public Person person() {
return new Person("王五", 20);
}
}
3.3 新建测试类:
public class BeanConfigurationTest extends TestCase {
@Test
public void testPerson() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfiguration.class);
Person person = applicationContext.getBean(Person.class);
System.out.println(person);
}
}
AnnotationConfigApplicationContext
表示使用注解的方式进行获取配置类,传入配置类作为参数,便获得了applicationContext
对象,接着便可以使用该对象进行获得bean对象了。
4. Bean扫描的方式
在xml中可以配置某个包下面的类可以进行全部扫描,避免了每个类都需要配置的烦恼
<context:component-scan base-package="com.entity"/>
这样便可以直接扫描该包下所有配置了注解的类
常用的注解类有以下几种:
@Controller
:一般用于Controller层
@Service
:一般用于Sercice层
@Reposity
:一般用于Dao层
@Component
:一般不建议使用,该注解无具体描述,只表示这是一个注解
可以使用Java的方式来进行配置
4.1 方式一
@ComponentScans(value = {
@ComponentScan(value = "com.entity"),
}
@Configuration
public class BeanScanConfiguration {
}
使用@ComponentScans
的目的是,该注解下,可以配置多个@CompoentScan
注解,便于扩展,当然jdk1.8以后,可以直接使用多个同名注解,也不会报错了。
上面的注解意思是扫描com.entity
包下的所有类
4.2 方式二
@ComponentScan(basePackageClasses = {Person.class, PersonDao.class, PersonService.class, PersonController.class, CarController.class})
作用:直接给定需要装配的类,会自动进行装配,不建议使用,了解即可
4.3 方式三
@ComponentScan(excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
})
作用:进行一些类的排除,FilterType
一共有五种,分别是:
FilterType.ANNOTATION
:排除或添加指定的注解
FilterType.ASSIGNABLE_TYPE
:排除或添加指定的类型
FilterType.ASPECTJ
:按照切面进行排除或添加
FilterType.REGEX
:按照正则表达式排除或添加
FilterType.CUSTOM
:自定义排除或添加,需要实现TypeFilter接口
介绍自定义排除:
public class MyTypeFilter implements TypeFilter {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获得元数据信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
annotationMetadata.getAnnotationTypes().forEach(System.out::println);
ClassMetadata classMetadata = metadataReader.getClassMetadata();
System.out.println(classMetadata.getClassName());
Resource resource = metadataReader.getResource();
System.out.println(resource.getURI());
if (classMetadata.getClassName().contains("red")) {
return true;
}
return false;
}
}
使用方法:
@ComponentScan(includeFilters = {
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
})
同理,其他的需要添加进来的类,也可以按照相同的方法进行添加,即便刚排除了,然后又添加了,那依然算最后添加进来的,注解为@includeFilters
5. 使用Import进行导入
@Import(value = {Red.class, Green.class, PersonDao.class})
@Configuration
public class BeanImportConfiguration {
}
作用:导入对应的实体类
5.1 自定义import导入
可以实现ImportSelector
或ImportBeanDefinitionRegistrar
接口
5.1.1 实现ImportSelector
的方式
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
importingClassMetadata.getAnnotationTypes().forEach(System.out::println);
return new String[]{"entity.Yellow"};
}
}
返回一个String数组,数组里面保存的是需要装配的对象的包+对象名
5.1.2 实现ImportBeanDefinitionRegistrar
的方式
与上述方法不同的是,Register
可以自己注册bean,上面那个需要等待别人装配,只是返回需要装配的对象的位置而已。
public class MyImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition("entity.Red")) {
BeanDefinition beanDefinition = new RootBeanDefinition(Black.class);
registry.registerBeanDefinition("black", beanDefinition);
}
}
}
可以注册别名,如果不注册,默认为对象名
6. 使用条件注解@Conditional
进行装配
注册之前,需要实现Condition
接口
public class WindowCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
if (property.contains("Windows")) {
return true;
}
return false;
}
}
public class LinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
if (property.contains("Linux")) {
return true;
}
return false;
}
}
上面注册了两个条件,如果当前为Window环境,对应的返回true,表示可装配,否则返回false,表示不可装配
具体的配置类:
@Configuration
public class BeanConditionConfiguration {
@Conditional(WindowCondition.class)
@Bean
public Person createPerson() {
return new Person("Bill", 20);
}
@Conditional(LinuxCondition.class)
@Bean
public Person person() {
return new Person("Linus", 30);
}
}
在测试类中,只输出了一个bean对象
7. 使用BeanFactory
进行装配
使用需要实现BeanFactory
接口
具体的实现如图
public class ColorFactoryBean implements FactoryBean {
@Override
public boolean isSingleton() {
//是否单例
return true;
}
@Override
public Object getObject() throws Exception {
//需要返回的对象
return new Blue();
}
@Override
public Class<?> getObjectType() {
//需要返回的对象
return Blue.class;
}
}
配置类
@Configuration
public class BeanFactoryConfiguration {
@Bean
public ColorFactoryBean createColor() {
return new ColorFactoryBean();
}
}
测试结果:虽然装配的是ColorFactoryBean
,但是得到的却是Color
,如果需要得到工厂类对象,需要获取的时候这样进行获取
Object bean = applicationContext.getBean("&createColor");
这样获得的对象就是工厂对象本身,而不是装配的对象