Spring基础总结(中)

13. 实现 AOP 的方式

  1. 通过 ProxyFactory 实现,注意这和 Proxy 不同,如下的 User 类不需要实现接口
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(new CService());

proxyFactory.addAdvice(new MethodInterceptor() {
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("Before ...");
        Object result = invocation.proceed();
        System.out.println("After ...");
        return result;
    }
});

CService cService = (CService) proxyFactory.getProxy();
cService.print();
  1. 通过定义 ProxyFactoryBean
@Bean
public ProxyFactoryBean cServiceProxy() {
        ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
        proxyFactoryBean.setTarget(new CService());
        proxyFactoryBean.addAdvice(new MethodInterceptor() {
            public Object invoke(MethodInvocation invocation) throws Throwable {
                System.out.println("Before ...");
                Object result = invocation.proceed();
                System.out.println("After ...");
                return result;
            }
        });
        return proxyFactoryBean;
    }

// 调用
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
CService cService = (CService) context.getBean("cServiceProxy");
cService.print();
  1. 通过 BeanNameAutoProxyCreator
@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
    BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
    beanNameAutoProxyCreator.setBeanNames("CService"); //此处可为通配符, 例如: CS*
    beanNameAutoProxyCreator.setInterceptorNames("myAroundAdvice"); // 拦截器的方法名
    beanNameAutoProxyCreator.setProxyTargetClass(true);
    return beanNameAutoProxyCreator;
}

@Bean
public MethodInterceptor myAroundAdvice() {
        return new MethodInterceptor() {
            public Object invoke(MethodInvocation invocation) throws Throwable {
                System.out.println("Before ...");
                Object result = invocation.proceed();
                System.out.println("After ...");
                return result;
            }
        };
    }

// 调用
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
CService cService = (CService) context.getBean("CService");
cService.print();

注意:CService 上面要添加 @Component 注解,1) 和 2) 则不用

  1. 通过 DefaultPointcutAdvisor
@Bean
public DefaultPointcutAdvisor defaultPointcutAdvisor() {
    NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
    pointcut.addMethodName("print"); // 指定要切面处理的方法

    DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
    defaultPointcutAdvisor.setPointcut(pointcut);
    // 添加切面
    defaultPointcutAdvisor.setAdvice(new MethodInterceptor() {
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("Before ...");
            Object result = invocation.proceed();
            System.out.println("Before ...");
            return result;
        }
    });
    return defaultPointcutAdvisor;
}

// DefaultAdvisorAutoProxyCreator 也可以在 AppConfig 上面通过 @Import(DefaultAdvisorAutoProxyCreator.class) 引入
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    return defaultAdvisorAutoProxyCreator;
}

// 调用
CService cService = (CService) context.getBean("CService");
cService.print();

注意:AppConfig 上面不要 @EnableAspectJAutoProxy 注解,否则会报错:com.sun.proxy.$Proxy19 cannot be cast to com.spring.demo.service.CService

14. Spring 中实现国际化

方式一:通过 applicationContext 获取

  1. 在 AppConfig 中添加如下代码
@Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasename("message"); // 配置文件前缀,可传入多个
    return messageSource;
}
  1. 在 src 目录下创建两个 properties 文件
  • message.properties 存放中文信息键值对: code = 测试
  • message_en.properties 存放英文信息键值对:code = test
  1. 调用测试
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// 中文,此处其实是没有 message_en_CN.properties 配置文件,所以会取默认的 message.properties 中的值
String cnCode = context.getMessage("code", null, new Locale("en_CN"));
System.out.println(cnCode);
// 英文
String enCode = context.getMessage("code", null, new Locale("en"));
System.out.println(enCode);

方式二:自定义类实现 MessageSourceAware 接口

  1. 在 AppConfig 中添加如下代码
@Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasename("message"); // 配置文件前缀,可传入多个
    return messageSource;
}
  1. 新建 MessageSourceService 实现 MessageSourceAware 接口
@Component
public class MessageSourceService implements MessageSourceAware {
    @Resource
    private MessageSource messageSource;

    public void setMessageSource(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    /**
     * 定义取值的方法
     */
    public String getValue(String key, String env) {
        return messageSource.getMessage(key, null, new Locale(env));
    }
}

// 调用
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MessageSourceService messageSourceService = (MessageSourceService) context.getBean("messageSourceService");
String cnCode = messageSourceService.getValue("code", "en_CN");
System.out.println(cnCode);

String enCode = messageSourceService.getValue("code", "en");
System.out.println(enCode);

15. 获取运行时环境

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
ConfigurableEnvironment environment = context.getEnvironment();
System.out.println(environment.getSystemProperties());  // 获取系统运行时环境信息
System.out.println(environment.getSystemEnvironment()); // 获取系统信息
System.out.println(environment.getProperty("name")); // 获取application.properties 中的键值对

16. 事件发布

主要在 Spring 初始化完成后执行;实现方式有 3 种

  1. 定义一个 AppListener 类并实现 ApplicationListener 接口,实现其 onApplicationEvent 方法
@Component
public class AppListener implements ApplicationListener {
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof PayloadApplicationEvent) {
            PayloadApplicationEvent e = (PayloadApplicationEvent) event;
            System.out.println("1. " + e.getPayload());
        }
    }
}

使用 ApplicationContext 直接发布

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// 发布事件
context.publishEvent("aaaaaaaaaa");
  1. 直接注入 ApplicationEventMulticaster
@Component
public class CService {
    @Resource
    private ApplicationEventMulticaster applicationEventMulticaster;

    public void print() {
        // 在方法中执行如下代码发布
        applicationEventMulticaster.multicastEvent(new PayloadApplicationEvent <String> (this, "cccc"));
        System.out.println("CService print() method executed");
    }
}

调用 print 方法发布

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
CService cService = (CService) context.getBean("CService");
cService.print();
  1. 在方法上添加 @EventListener 注解
@EventListener
public void test(ApplicationEvent event) {
    if (event instanceof PayloadApplicationEvent) {
        PayloadApplicationEvent < String > e = (PayloadApplicationEvent < String > ) event;
        System.out.println("2. " + e.getPayload());
    }
}

17. 元数据读取器

public static void main(String[] args) throws IOException {
    SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();
    MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader(CService.class.getName());
    ClassMetadata classMetadata = metadataReader.getClassMetadata();
    // 获取类名称
    System.out.println(classMetadata.getClassName());
    // 获取类注解
    AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
    annotationMetadata.getAnnotationTypes().forEach(annotation - > System.out.println(annotation));
}

18. 获取 Spring 上下文用于获取项目初始化完成后的 Bean 对象

@Component
public class SpringContext implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if(null == SpringContext.applicationContext) {
            SpringContext.applicationContext = applicationContext;
        }
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static Object getBean(String name){
        return getApplicationContext().getBean(name);
    }

    public static <T> T getBean(Class<T> clazz){
        return getApplicationContext().getBean(clazz);
    }

    public static <T> T getBean(String name, Class<T> clazz){
        return getApplicationContext().getBean(name, clazz);
    }

    public static Environment getEnvironment() {
        return applicationContext.getEnvironment();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值