AnnotationConfigApplicationContext 基于注解的 Spring 上下文,也可以说成是 Spring 的容器
ClassPathXmlApplicationContext 基于 XML 上线文,Spring 容器,(PS:目前较少使用,主要是 Spirng-Boot 主推注解方式)
AnnotationConfigApplicationContext
使用 AnnotationConfigApplicationContext 可以实现基于 Java 的配置类加载Spring的应用上下文。不用使用spring-context.xml进行配置。也可以通过@Bean @Component等方式创建Bean, 相比 XML 配置, 更加便捷。
ClassPathXmlApplicationContext
ClassPathXmlApplicationContext 是 spring 读取 xml 最常用的类。而我们一般操作的是它的接口ApplicationContext。BeanFactory和ApplicationContext区别不大,BeanFactory不在自动 BeanPostProcessor 和自动 BeanFactoryPostProcessor 上注册。使用中我们尽量用ApplicationContext。
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
UserService UserSrv =(UserService)ctx.getBean("userService");
ApplicationEvent 是 Spring 提供的事件驱动编程,也可以看作观察者模式的一个编程范本,支持同步监听和异步监听两种方式。
定义事件:
public class TestEvent extends ApplicationEvent {
public TestEvent(Object source){
super(source);}}
1.
2.
3.
4.
5.
6.
定义事件监听器:
public class TestListener implements ApplicationListener<TestEvent>{
@Override
public void onApplicationEvent(TestEvent event){
System.out.println("收到一个事件 ,,,,,");}}
1.
2.
3.
4.
5.
6.
7.
调用程序:
@Configuration
public class ApplicationEventTest {
@Bean
public ApplicationListener applicationListener(){
return new TestListener();}
public static void main(String[] args){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationEventTest.class);
context.publishEvent(new TestEvent(new Object()));}}
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Spring 容器启动过程中有很多启动过程的事件,我们可以通过这种方式来实现,在Spring 容器启动过后初始化一些内容:比如初始化系统参数到服务的本地内存等。不过我们需要注意的是 Spring 的事件机制只是一个本地事件,没有持久化机制。所以可靠性不能完全保证。
类型转换
Spring 内部,有很多地方可能需要将 String 转换为其他类型,今天我们一起来学习一下 PropertyEditor、 ConversionService、TypeConverter 三种类型转换的使用。
PropertyEditor 类型转换器
PropertyEditor 是 JDK 提供的类型转换器,首先创建 bean :
@Service
public class OrderService {
@Value("orderVal")
private Orderorder;
public void test(){
System.out.println("test order : "+order);}}
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
创建类型转换器,将字符串转换为 Order 实例对象。
public class String2ObjectPropertyEditor extends PropertyEditorSupport implements PropertyEditor {
@Override
public void setAsText(String text) throws IllegalArgumentException {Orderorder= new Order();order.setName("haha");order.setAge(12);
this.setValue(order);}}
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
注册转换器以及测试代码:
@Import({OrderService.class})
@Configuration
public class PropertyEditorTest {
@Bean
public CustomEditorConfigurer customEditorConfigurer(){
Map<Class<?>, Class<? extends PropertyEditor>> customEditors = new HashMap<>();
customEditors.put(Order.class, String2ObjectPropertyEditor.class);
CustomEditorConfigurer customEditorConfigurer = new CustomEditorConfigurer();
customEditorConfigurer.setCustomEditors(customEditors);
return customEditorConfigurer;}
public static void main(String[] args){// 使用方式 1
String2ObjectPropertyEditor propertyEditor = new String2ObjectPropertyEditor();
propertyEditor.setAsText("1");
Object value = propertyEditor.getValue();
System.out.println(value);// 使用方式 2
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(PropertyEditorTest.class);
OrderService orderItemService = applicationContext.getBean(OrderService.class);
orderItemService.test();}}
public class String2ObjectConversionService implements ConditionalGenericConverter {
@Override
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType){
return
Objects.equals(sourceType.getType(), String.class)&&
Objects.equals(targetType.getType(),Order.class);}
@Override
public Set<ConvertiblePair> getConvertibleTypes(){
return Collections.singleton(new ConvertiblePair(String.class,Order.class));}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType){
return new Order("haha",32);}}
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
单独使用
DefaultConversionService conversionService = new DefaultConversionService();
conversionService.addConverter(new String2ObjectConversionService());Orderorder= conversionService.convert("1",Order.class);
System.out.println(order);
1.
2.
3.
4.
在 Spring 中使用:
@Bean
public ConversionServiceFactoryBean conversionService(){
ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean();
conversionServiceFactoryBean.setConverters(Collections.singleton(new String2ObjectConversionService()));
return conversionServiceFactoryBean;
}
1.
2.
3.
4.
5.
6.
7.
8.
Bean 的注入和调用代码:
// 测试和注入
@Service
public class OrderService {
//通过 @Value 注入
@Value("orderVal")
private Order order;
public void test(){
System.out.println("test order : " + order);
}
}
// 调用代码
ApplicationContext appliciton = new AnnotationConfigApplicationContext(ConvertTest.class);
OrderItemService orderItemService = appliciton.getBean(OrderItemService.class);
orderItemService.test();
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
TypeConverter 类型转换器
TypeConverter 整合了 PropertyEditor 和 ConversionService, 在 Spring 内部使用:
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
typeConverter.registerCustomEditor(Order.class, new String2ObjectPropertyEditor());Orderorder= typeConverter.convertIfNecessary("orderVal",Order.class);
System.out.println(order);
1.
2.
3.
4.
比如在 AbstractBeanFacotry#adaptBeanInstance 中也有用到:
// AbstractBeanFacotry.java<T> T adaptBeanInstance(String name, Object bean, @Nullable Class<?> requiredType){// Check if required type matches the type of the actual bean instance.
// 如果转换类型不为空,并且 bean 类型与目标类型不匹配
if (requiredType !=null&&!requiredType.isInstance(bean)){
try {// 尝试转换
Object convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean ==null){
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}
return (T) convertedBean;}
catch (TypeMismatchException ex){
if (logger.isTraceEnabled()){
logger.trace("Failed to convert bean '"+ name +"' to required type '"+
ClassUtils.getQualifiedName(requiredType)+"'", ex);}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}
return (T) bean;}
public class B implements Ordered {
@Override
public int getOrder(){
return 2;}}
public class A implements Ordered {
@Override
public int getOrder(){
return 1;}}
public class OrderComparatorTest {
public static void main(String[] args){
A a = new A();
B b = new B();
OrderComparator orderComparator = new OrderComparator();
System.out.println(orderComparator.compare(a, b));//-1
List list = new ArrayList();
list.add(a);
list.add(b);
list.sort(orderComparator);
System.out.println(list);// a,b
}}
1.
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.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
另外,Spring 还提供了一个 OrderComparator 的子类:AnnotationAwareOrderComparator, 它支持 @Order 注解来指定 order 的值,比如:
@Order(1)
public class A1 {}
@Order(1)
public class B1 {}
public class OrderComparatorTest1 {
public static void main(String[] args){
A1 a = new A1();
B1 b = new B1();
AnnotationAwareOrderComparator orderComparator = new AnnotationAwareOrderComparator();
System.out.println(orderComparator.compare(a, b));//-1
List list = new ArrayList();
list.add(a);
list.add(b);
list.sort(orderComparator);
System.out.println(list);// a,b
}}
@Component
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("bean factory post processor");}}
@ComponentScan(value ="com.summer.test.service",
excludeFilters ={
@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = UserService.class)})
public class AppConfig {}
@ComponentScan(value ="com.summer.test.service",
includeFilters ={
@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = UserService.class)})
public class AppConfig {}