3、Spring常用方法案例

@ComponentScan(value = "com.xuyuan")
public class AppConfig {

}
public class SendService {

    public void test(){
        System.out.println("send");
    }

}
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        // 生成一个BeanDefinition对象,并设置beanClass为MoneyService.class,并注册到ApplicationContext中
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        beanDefinition.setBeanClass(MoneyService.class);
        beanDefinition.setScope("prototype");
        context.registerBeanDefinition("moneyService",beanDefinition);
        MoneyService moneyService = (MoneyService)context.getBean("moneyService");
        MoneyService moneyService1 = (MoneyService)context.getBean("moneyService");
        System.out.println(moneyService);
        System.out.println(moneyService1);
}

运行结果:

com.xuyuan.service.MoneyService@2e6a8155
com.xuyuan.service.MoneyService@6221a451
        可以直接把某个类转换为BeanDefinition,并且会解析该类上的注解,比如
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context);
        annotatedBeanDefinitionReader.register(MoneyService.class);
        MoneyService moneyService = (MoneyService)context.getBean("moneyService");
        System.out.println(moneyService);
}

运行结果:

com.xuyuan.service.MoneyService@2e6a8155
        注意:它能解析的注解是:@Conditional,@Scope 、@Lazy、@Primary、@DependsOn、@Role、@Description
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-4.2.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

<bean id="moneyService" class="com.xuyuan.service.MoneyService"/>

</beans>
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context);
        int i = xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
        System.out.println(context.getBean("moneyService"));
}

运行结果:

com.xuyuan.service.MoneyService@563f38c4

        ClassPathBeanDefinitionScanner是扫描器,但是它的作用和BeanDefinitionReader类似,它可以 进行扫描,扫描某个包路径,对扫描到的类进行解析,比如,扫描到的类上如果存在@Component 注解,那么就会把这个类解析为一个BeanDefinition,比如:
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.refresh();
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
        int scan = scanner.scan("com.xuyuan");
        System.out.println(context.getBean("moneyService"));
}

运行结果:

com.xuyuan.service.MoneyService@8646db9
public static void main(String[] args) {
        DefaultListableBeanFactory beanfactory = new DefaultListableBeanFactory();
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        beanDefinition.setBeanClass(MoneyService.class);
        beanfactory.registerBeanDefinition("moneyService",beanDefinition);
        System.out.println(beanfactory.getBean("moneyService"));
}

运行结果:

com.xuyuan.service.MoneyService@7b1d7fff

国际化

@ComponentScan(value = "com.xuyuan")
public class AppConfig {

    @Bean
    public MessageSource messageSource(){
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("messages");
        return  messageSource;
    }
}
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        //国际化
        String message = context.getMessage("test", null, new Locale("en"));
        System.out.println(message);
}

messages.propertiesmessages_en.properties
test=atest=b

运行结果:

b

资源加载

public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        Resource resource = context.getResource("spring.properties");
        try {
            File file = resource.getFile();
            URL url = resource.getURL();
            String file1 = url.getFile();
            if(file.isFile()){
                System.out.println("file");
            }
            System.out.println("----------"+resource.contentLength());
        } catch (IOException e) {
            e.printStackTrace();
        }
}

spring.properties

a=1

b=2

c=3

运行结果:

file
----------13
public static void main(String[] args) throws IOException {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        Resource resource = context.getResource("file://D:\\zyyangy\\workspace\\self_growth\\spring-test-demo\\src\\main\\java\\com\\xuyuan\\AppConfig.java");
        System.out.println(resource.contentLength());
        System.out.println(resource.getFilename());
        Resource resource1 = context.getResource("https://www.baidu.com");
        System.out.println(resource1.contentLength());
        System.out.println(resource1.getURL());
        Resource resource2 = context.getResource("classpath:spring.xml");
        System.out.println(resource2.contentLength());
        System.out.println(resource2.getURL());
}

运行结果:

4305
AppConfig.java
2443
https://www.baidu.com
743
file:/D:/zyyangy/workspace/self_growth/spring-test-demo/target/classes/spring.xml

运行时环境

@PropertySource("classpath:spring.properties")
@ComponentScan(value = "com.xuyuan")
public class AppConfig { 
}
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        Map<String, Object> systemEnvironment = context.getEnvironment().getSystemEnvironment();
        System.out.println(systemEnvironment);
        System.out.println("=======");
        Map<String, Object> systemProperties = context.getEnvironment().getSystemProperties();
        System.out.println(systemProperties);
        System.out.println("=======");
        //包含最全的信息
        MutablePropertySources propertySources = context.getEnvironment().getPropertySources();
        System.out.println(propertySources);
        System.out.println("=======");

        System.out.println(context.getEnvironment().getProperty("NO_PROXY"));
        System.out.println(context.getEnvironment().getProperty("sun.jnu.encoding"));
        System.out.println(context.getEnvironment().getProperty("a"));
}

运行结果:

[PropertiesPropertySource {name='systemProperties'}, SystemEnvironmentPropertySource {name='systemEnvironment'}, ResourcePropertySource {name='class path resource [spring.properties]'}]
=======
null
GBK
1

Process finished with exit code 0

事件发布

@ComponentScan(value = "com.xuyuan")
public class AppConfig { 

    @Bean
    public ApplicationListener applicationListener(){
        return new ApplicationListener() {
            public void onApplicationEvent(ApplicationEvent event) {
                System.out.println("接收到一个事件"+event.getSource());
            }
        };
    }
}
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        context.publishEvent("start event");
}

运行结果:

接收到一个事件org.springframework.context.annotation.AnnotationConfigApplicationContext@7a07c5b4, started on Wed Mar 20 15:49:15 CST 2024
接收到一个事件org.springframework.context.annotation.AnnotationConfigApplicationContext@7a07c5b4, started on Wed Mar 20 15:49:15 CST 2024

类型转换

JDK中提供的类型转化工具类
public class User {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class StringToUserPropertyEditor extends PropertyEditorSupport implements PropertyEditor {

    @Override
    public void setAsText(String text) throws java.lang.IllegalArgumentException {
        User user = new User();
        user.setName(text);
        this.setValue(user);
    }
}
public static void main(String[] args) {
        StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor();
        propertyEditor.setAsText("1");
        User user = (User) propertyEditor.getValue();
        System.out.println(user);
        System.out.println(user.getName());
}

运行结果:

com.xuyuan.service.User@4d7e1886
1
@ComponentScan(value = "com.xuyuan")
public class AppConfig {
    
    @Bean
    public CustomEditorConfigurer customEditorConfigurer(){
        CustomEditorConfigurer customEditorConfigurer = new CustomEditorConfigurer();
        HashMap<Class<?>, Class<? extends PropertyEditor>> propertyEditorMap = new HashMap<>();
        // 表示StringToUserPropertyEditor可以将String转化成User类型,在Spring源码中,如果发现当前对象是String,而需要的类型是User,就会使用该PropertyEditor来做类型转化
        propertyEditorMap.put(User.class,StringToUserPropertyEditor.class);
        customEditorConfigurer.setCustomEditors(propertyEditorMap);
        return customEditorConfigurer;
    }
}
@Component
public class PayService {

    @Value("xuanyuan")
    private User user;

    public void test(){
        System.out.println(user.getName());
    }
}
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        PayService payService = (PayService) context.getBean("payService");
        payService.test();
}

运行结果:

xuanyuan
public class StringToUserConverter implements ConditionalGenericConverter {

    @Override
    public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
        return sourceType.getType().equals(String.class) && targetType.getType().equals(User.class);
    }

    @Override
    public Set<ConvertiblePair> getConvertibleTypes() {
        return Collections.singleton(new ConvertiblePair(String.class,User.class));
    }

    @Override
    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
        User user = new User();
        user.setName((String) source);
        return user;
    }
}
 public static void main(String[] args) {
        DefaultConversionService conversionService = new DefaultConversionService();
        conversionService.addConverter(new StringToUserConverter());
        User value = conversionService.convert("1", User.class);
        System.out.println(value.getName());
}

运行结果:

1
@ComponentScan(value = "com.xuyuan")
public class AppConfig {

    @Bean
    public ConversionServiceFactoryBean conversionService(){
        ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean();
        conversionServiceFactoryBean.setConverters(Collections.singleton(new StringToUserConverter()));
        return conversionServiceFactoryBean;
    }
}
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        PayService payService = (PayService) context.getBean("payService");
        payService.test();
}

运行结果:

xuanyuan
public static void main(String[] args) {

        SimpleTypeConverter typeConverter = new SimpleTypeConverter();
        typeConverter.registerCustomEditor(User.class,new StringToUserPropertyEditor());
//        typeConverter.setConversionService(conversionService);
        User user = typeConverter.convertIfNecessary("1", User.class);
        System.out.println(user.getName());
    }
}

运行结果:

1

比较器

//@Order(3)
public class A implements Ordered {
    @Override
    public int getOrder() {
        return 3;
    }

    @Override
    public String toString() {
        return this.getClass().getSimpleName();
    }
}
//@Order(2)
public class B implements Ordered {
    @Override
    public int getOrder() {
        return 2;
    }

    @Override
    public String toString() {
        return this.getClass().getSimpleName();
    }
}
public static void main(String[] args) {
        A a = new A();
        B b = new B();
        OrderComparator comparator = new OrderComparator();
        System.out.println(comparator.compare(a,b));
        List list = new ArrayList<>();
        list.add(a);
        list.add(b);
        list.sort(comparator);
        System.out.println(list);
}

运行结果:

1
[B, A]
public static void main(String[] args) {
        A a = new A();
        B b = new B();
        AnnotationAwareOrderComparator comparator = new AnnotationAwareOrderComparator();
        System.out.println(comparator.compare(a,b));
        List list = new ArrayList<>();
        list.add(a);
        list.add(b);
        list.sort(comparator);
        System.out.println(list);
}

运行结果:

1
[com.xuyuan.service.Order.B@4dcbadb4, com.xuyuan.service.Order.A@4e515669]
MetadataReader、ClassMetadata、AnnotationMetadata
        在Spring中需要去解析类的信息,比如类名、类中的方法、类上的注解,这些都可以称之为类的元数 据,所以Spring中对类的元数据做了抽象,并提供了一些工具类。
        MetadataReader表示类的元数据读取器,默认实现类为SimpleMetadataReader。
@Service
public class MoneyService {

    class person{

    }
}
public static void main(String[] args) throws IOException {
        SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();
        //构造一个MetadataReader
        MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("com.xuyuan.service.MoneyService");
        //得到一个ClassMetadata,并获取类名
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        System.out.println(classMetadata.getClassName());
        System.out.println(classMetadata.getInterfaceNames());//实现类
        System.out.println(classMetadata.getMemberClassNames()[0]);
        //获取一个AnnotationMetadata,并获取类上的注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        System.out.println(annotationMetadata.hasMetaAnnotation(Component.class.getName()));
        System.out.println(annotationMetadata.hasAnnotatedMethods(Component.class.getName()));
        for (String annotationType : annotationMetadata.getAnnotationTypes()) {
            System.out.println(annotationType);
        }
}

运行结果:

com.xuyuan.service.MoneyService
[Ljava.lang.String;@7637f22
com.xuyuan.service.MoneyService$person
true
false
org.springframework.stereotype.Service
        需要注意的是,SimpleMetadataReader去解析类时,使用的ASM技术
        为什么要使用ASM技术,Spring启动的时候需要去扫描,如果指定的包路径比较宽泛,那么扫描的类是非常多的,那如果在Spring启动时就把这些类全部加载进JVM了,这样不太好,所以使用了ASM技术。
ExcludeFilter和IncludeFilter
@ComponentScan(value = "com.xuyuan",excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = UserService.class)})
public class AppConfig {
}
@Component
public class UserService{

}
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        System.out.println(context.getBean("userService"));
}

运行结果:

No bean named 'userService' available
@ComponentScan(value = "com.xuyuan",includeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = UserService.class)})
public class AppConfig {
}
public class UserService {
}
public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        System.out.println(context.getBean("userService"));
}

运行结果:

com.xuyuan.service.UserService@2c1b194a
FilterType分为:
        1. ANNOTATION:表示是否包含某个注解
        2. ASSIGNABLE_TYPE:表示是否是某个类
        3. ASPECTJ:表示否是符合某个Aspectj表达式
        4. REGEX:表示是否符合某个正则表达式
        5. CUSTOM:自定义
        在Spring的扫描逻辑中,默认会添加一个AnnotationTypeFilter给includeFilters,表示默认情况下Spring扫描过程中会认为类上有@Component注解的就是Bean。
FactoryBean
public class CommodityService {

    public void test(){
        System.out.println("商品");
    }

}
@Component
public class XuanYuanFactoryBean implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        CommodityService commodityService = new CommodityService();
        return commodityService;
    }

    @Override
    public Class<?> getObjectType() {
        return CommodityService.class;
    }
}
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        System.out.println(context.getBean("xuanYuanFactoryBean"));
        System.out.println(context.getBean("&xuanYuanFactoryBean"));
}
运行结果:
com.xuyuan.service.CommodityService@6d4e5011
com.xuyuan.service.XuanYuanFactoryBean@57d7f8ca
        通过上面这段代码,我们自己创造了一个CommodityService 对象,并且它将成为Bean。但是通过这种方式创造出来的CommodityService 的Bean,只会经过初始化后,其他Spring的生命周期步骤是不会经过的比如依赖注入。
        
        通过@Bean也可以自己生成一个对象作为Bean,那么和FactoryBean的区别是什么呢?其实在很多场景下他俩是可以替换的,但是站在原理层面来说的,区别很明显,@Bean定义的Bean是会经过完整的Bean生命周期的。
BeanPostProcessor
@Component("commodityService")
public class XuanYuanFactoryBean implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        CommodityService commodityService = new CommodityService();
        return commodityService;
    }

    @Override
    public Class<?> getObjectType() {
        return CommodityService.class;
    }
}
@Component
public class XuanYuanBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if("commodityService".equals(beanName)){
            System.out.println("初始化前"+bean);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if("commodityService".equals(beanName)){
            System.out.println("初始化后"+bean);
        }
        return bean;
    }
}
public class CommodityService {
    public void test(){
        System.out.println("商品");
    }
}
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        System.out.println(context.getBean("commodityService"));
}

运行结果:

初始化前com.xuyuan.service.XuanYuanFactoryBean@41a0aa7d
初始化后com.xuyuan.service.XuanYuanFactoryBean@41a0aa7d

初始化后com.xuyuan.service.CommodityService@795509d9
com.xuyuan.service.CommodityService@2f54a33d

BeanFactoryPostProcessor
@Component
public class XuanYanBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("加工beanFactory"+beanFactory);
    }
}
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        System.out.println(context.getBean("commodityService"));
}
运行结果:

加工beanFactoryorg.springframework.beans.factory.support.DefaultListableBeanFactory@544fe44c

初始化前com.xuyuan.service.XuanYuanFactoryBean@41a0aa7d
初始化后com.xuyuan.service.XuanYuanFactoryBean@41a0aa7d

初始化后com.xuyuan.service.CommodityService@795509d9
com.xuyuan.service.CommodityService@2f54a33d

        BeanFactoryPostProcessor表示Bean工厂的后置处理器,其实和BeanPostProcessor类似,
BeanPostProcessor是干涉Bean的创建过程,BeanFactoryPostProcessor是干涉BeanFactory的创
建过程。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值