> 文章列表 > Spring基础总结(中)

Spring基础总结(中)

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 {@Resourceprivate 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 {@Resourceprivate 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;@Overridepublic 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();}
}