Spring 使用
基础配置
依赖注入
- POM
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.12</version>
</dependency>
- 配置
@Configuration //1
@ComponentScan("com.wisely.highlight_spring4.ch1.di") //2
public class DiConfig {
}
- 功能类Bean
@Service //1
public class FunctionService {
public String sayHello(String word){
return "Hello " + word +" !";
}
}
- 使用功能类的Bean
@Service //1
public class UseFunctionService {
@Autowired //2
FunctionService functionService;
public String SayHello(String word){
return functionService.sayHello(word);
}
}
- 运行
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DiConfig.class); //1
UseFunctionService useFunctionService = context.getBean(UseFunctionService.class); //2
System.out.println(useFunctionService.SayHello("world"));
context.close();
}
}
- 结果
Hello world !
Java 配置
- POM
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.12</version>
</dependency>
- 功能类Bean
public class FunctionService {
public String sayHello(String word){
return "Hello " + word +" !";
}
}
- 使用功能类Bean
public class UseFunctionService {
FunctionService functionService;
public void setFunctionService(FunctionService functionService) {
this.functionService = functionService;
}
public String SayHello(String word){
return functionService.sayHello(word);
}
}
- 配置
@Configuration
public class JavaConfig {
@Bean
public FunctionService functionService(){
return new FunctionService();
}
@Bean
public UseFunctionService useFunctionService(){
UseFunctionService useFunctionService = new UseFunctionService();
useFunctionService.setFunctionService(functionService()); //3 方式一
return useFunctionService;
}
// @Bean
// public UseFunctionService useFunctionService(FunctionService functionService){// 方式二
// UseFunctionService useFunctionService = new UseFunctionService();
// useFunctionService.setFunctionService(functionService);
// return useFunctionService;
// }
}
- 运行
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);
UseFunctionService useFunctionService = context.getBean(UseFunctionService.class);
System.out.println(useFunctionService.SayHello("java config"));
context.close();
}
}
- 结果
Hello java config !
AOP
- POM
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.12</version>
</dependency>
<!-- spring aop支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.12</version>
</dependency>
<!-- aspectj支持 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
- 拦截规则
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Action {
String name();
}
- 使用注解的被拦截类
@Service
public class DemoAnnotationService {
@Action(name="注解式拦截的add操作")
public void add(){}
}
- 使用方法规则被拦截类
@Service
public class DemoMethodService {
public void add(){}
}
- 切面
@Aspect //1
@Component //2
public class LogAspect {
@Pointcut("@annotation(com.wisely.highlight_spring4.ch1.aop.Action)") //3
public void annotationPointCut(){};
@After("annotationPointCut()") //4
public void after(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Action action = method.getAnnotation(Action.class);
System.out.println("注解式拦截 " + action.name()); //5
}
@Before("execution(* com.wisely.highlight_spring4.ch1.aop.DemoMethodService.*(..))") //6
public void before(JoinPoint joinPoint){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
System.out.println("方法规则式拦截,"+method.getName());
}
}
- 配置类
@Configuration
@ComponentScan("com.wisely.highlight_spring4.ch1.aop")
@EnableAspectJAutoProxy //1
public class AopConfig {
}
- 运行
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AopConfig.class); //1
DemoAnnotationService demoAnnotationService = context.getBean(DemoAnnotationService.class);
DemoMethodService demoMethodService = context.getBean(DemoMethodService.class);
demoAnnotationService.add();
demoMethodService.add();
context.close();
}
}
- 结果
注解式拦截 注解式拦截的add操作
方法规则式拦截,add
常用配置
Scope
常用的有Singleton、Prototype、Request、Session、GlobalSession。
- POM
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.12</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
- 单例Bean
@Service //1
public class DemoSingletonService {
}
- 多例Bean
@Service
@Scope("prototype")//1
public class DemoPrototypeService {
}
- 配置类
@Configuration
@ComponentScan("com.wisely.highlight_spring4.ch2.scope")
public class ScopeConfig {
}
- 运行
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(ScopeConfig.class);
DemoSingletonService s1 = context.getBean(DemoSingletonService.class);
DemoSingletonService s2 = context.getBean(DemoSingletonService.class);
DemoPrototypeService p1 = context.getBean(DemoPrototypeService.class);
DemoPrototypeService p2 = context.getBean(DemoPrototypeService.class);
System.out.println("s1与s2是否相等:"+s1.equals(s2));
System.out.println("p1与p2是否相等:"+p1.equals(p2));
context.close();
}
}
- 结果
s1与s2是否相等:true
p1与p2是否相等:false
LE 和资源调用
主要在注解@Value 的参数中使用表达式
注入普通字符;注入操作系统属性;注入表达式运算结果;注入其他Bean的属性;注入文件内容;注入网址内容;注入属性文件。
- POM
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.12</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
- property配置文件
book.author=wangyunfei
book.name=spring boot
- 被注入的Bean
@Service
public class DemoService {
@Value("其他类的属性") //1
private String another;
public String getAnother() {
return another;
}
public void setAnother(String another) {
this.another = another;
}
}
- 配置类
@Configuration
@ComponentScan("com.wisely.highlight_spring4.ch2.el")
@PropertySource("classpath:com/wisely/highlight_spring4/ch2/el/test.properties")//7
public class ElConfig {
@Value("I Love You!") //1
private String normal;
@Value("#{systemProperties['os.name']}") //2
private String osName;
@Value("#{ T(java.lang.Math).random() * 100.0 }") //3
private double randomNumber;
@Value("#{demoService.another}") //4
private String fromAnother;
@Value("classpath:com/wisely/highlight_spring4/ch2/el/test.txt") //5
private Resource testFile;
@Value("http://www.baidu.com") //6
private Resource testUrl;
@Value("${book.name}") //7
private String bookName;
@Autowired
private Environment environment; //7
@Bean //7
public static PropertySourcesPlaceholderConfigurer propertyConfigure() {
return new PropertySourcesPlaceholderConfigurer();
}
public void outputResource() {
try {
System.out.println(normal);
System.out.println(osName);
System.out.println(randomNumber);
System.out.println(fromAnother);
System.out.println(IOUtils.toString(testFile.getInputStream()));
System.out.println(IOUtils.toString(testUrl.getInputStream()));
System.out.println(bookName);
System.out.println(environment.getProperty("book.author"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 运行
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ElConfig.class);
ElConfig resourceService = context.getBean(ElConfig.class);
resourceService.outputResource();
context.close();
}
}
- 结果
I Love You!
Windows 10
85.19568992822624
其他类的属性
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
spring boot
wangyunfei
Process finished with exit code 0
Bean 的创建与销毁
- POM
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.12</version>
</dependency>
- 使用@Bean 形式的Bean
public class BeanWayService {
public void init(){
System.out.println("@Bean-init-method");
}
public BeanWayService() {
super();
System.out.println("初始化构造函数-BeanWayService");
}
public void destroy(){
System.out.println("@Bean-destory-method");
}
}
- 使用JSR250形式的Bean
public class JSR250WayService {
@PostConstruct //1
public void init(){
System.out.println("jsr250-init-method");
}
public JSR250WayService() {
super();
System.out.println("初始化构造函数-JSR250WayService");
}
@PreDestroy //2
public void destroy(){
System.out.println("jsr250-destory-method");
}
}
- 配置类
@Configuration
@ComponentScan("com.wisely.highlight_spring4.ch2.prepost")
public class PrePostConfig {
@Bean(initMethod="init",destroyMethod="destroy") //1
BeanWayService beanWayService(){
return new BeanWayService();
}
@Bean
JSR250WayService jsr250WayService(){
return new JSR250WayService();
}
}
- 运行
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PrePostConfig.class);
BeanWayService beanWayService = context.getBean(BeanWayService.class);
JSR250WayService jsr250WayService = context.getBean(JSR250WayService.class);
context.close();
}
}
- 结果
初始化构造函数-BeanWayService
@Bean-init-method
初始化构造函数-JSR250WayService
jsr250-init-method
jsr250-destory-method
@Bean-destory-method
Profile
使用Profile可以在不同的环境使用不同的配置参数。环境设置方法有:
1、通过Environment的ActiveProfiles来设定当前context是哪个环境;(下文验证)
2、通过设定jvm的spring.profiles.active参数来配置环境;(未验证)
3、Web项目设置在Servlet的context parameter中。(未验证)
Servlet 2.5及以下:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>spring.profiles.active</param-name>
<param-value>production</param-value>
</init-param>
</servlet>
Servlet 3.0及以上:
public class WebInit implement WebApplicationInittializer {
@Override
public void onStartup(ServletContext container) throws ServletException {
container.serInitParameter("spring.profiles.default", "dev");
}
}
- POM
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.12</version>
</dependency>
- 实例Bean
public class DemoBean {
private String content;
public DemoBean(String content) {
super();
this.content = content;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
- Profile配置
@Configuration
public class ProfileConfig {
@Bean
@Profile("dev") //1
public DemoBean devDemoBean() {
return new DemoBean("from development profile");
}
@Bean
@Profile("prod") //2
public DemoBean prodDemoBean() {
return new DemoBean("from production profile");
}
}
- 运行
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles("dev"); //1
context.register(ProfileConfig.class);//2
context.refresh(); //3
DemoBean demoBean = context.getBean(DemoBean.class);
System.out.println(demoBean.getContent());
context.close();
}
}
- 结果
from development profile
事件
Spring的事件要遵循以下流程:
1、自定义事件,继承ApplicationEvent;
2、定义事件监听器,实现ApplicationListener;
3、定义容器发布事件。
- 自定义事件
public class DemoEvent extends ApplicationEvent{
private static final long serialVersionUID = 1L;
private String msg;
public DemoEvent(Object source,String msg) {
super(source);
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
- 事件监听器
@Component
public class DemoListener implements ApplicationListener<DemoEvent> {
public void onApplicationEvent(DemoEvent event) {
String msg = event.getMsg();
System.out.println("我(bean-demoListener)接受到了bean-demoPublisher发布的消息:" + msg);
}
}
- 事件发布类
@Component
public class DemoPublisher {
@Autowired
ApplicationContext applicationContext;
public void publish(String msg){
applicationContext.publishEvent(new DemoEvent(this, msg));
}
}
- 配置类
@Configuration
@ComponentScan("com.wisely.highlight_spring4.ch2.event")
public class EventConfig {
}
- 运行
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(EventConfig.class);
DemoPublisher demoPublisher = context.getBean(DemoPublisher.class);
demoPublisher.publish("hello application event");
context.close();
}
}
- 结果
我(bean-demoListener)接受到了bean-demoPublisher发布的消息:hello application event
Spring 高级话题
Spring Aware
Spring Aware 的目的是为了让Bean活的Spring容器的服务。Spring提供的Aware接口有:
- BeanNameAware:获得容器中Bean的名称;
- BeanFactoryAware:获得当前beanFatory,这样可以调用容器的服务;
- ApplicationContextAware*:当前的application context, 这样可以调用容器的服务;
- MessageSourceAware:获得message source,这样可以获得文本信息;
- ApplicationEventPublisherAware:应用事件发布器,可以发布事件;
- ResourceLoaderAware:获得资源加载器,可以获得外部资源文件。
代码示例:
- Spring Aware演示的Bean
@Service
public class AwareService implements BeanNameAware, ResourceLoaderAware {//1
private String beanName;
private ResourceLoader loader;
public void setResourceLoader(ResourceLoader resourceLoader) {//2
this.loader = resourceLoader;
}
public void setBeanName(String name) {//3
this.beanName = name;
}
public void outputResult() {
System.out.println("Bean的名称为:" + beanName);
Resource resource = loader.getResource("classpath:com/wisely/highlight_spring4/ch3/aware/test.txt");
try {
System.out.println("ResourceLoader加载的文件内容为: " + IOUtils.toString(resource.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 配置类
@Configuration
@ComponentScan("com.wisely.highlight_spring4.ch3.aware")
public class AwareConfig {
}
- 运行
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AwareConfig.class);
AwareService awareService = context.getBean(AwareService.class);
awareService.outputResult();
context.close();
}
}
- 结果
Bean的名称为:awareService
ResourceLoader加载的文件内容为: 111111
多线程
使用ThreadPoolTaskExecutor 可实现一个基于线程池的TaskExecutor。而实际开发中任务一般是非阻碍的,即异步的,所以在配置类中通过@EnableAsync开启对异步任务的支持,并通过在实际执行的Bean的方法中使用@Async注解来声明一个异步任务。
注意:ThreadPoolTaskExecutor 其实是对jdk的ThreadPoolExecutor的一层封装。
- 配置类
@Configuration
@ComponentScan("com.wisely.highlight_spring4.ch3.taskexecutor")
@EnableAsync //1
public class TaskExecutorConfig implements AsyncConfigurer{//2
public Executor getAsyncExecutor() {//2
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5);
taskExecutor.setMaxPoolSize(10);
taskExecutor.setQueueCapacity(25);
taskExecutor.initialize();
return taskExecutor;
}
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
- 任务执行类
@Service
public class AsyncTaskService {
@Async //1
public void executeAsyncTask(Integer i){
System.out.println("执行异步任务: "+i);
}
@Async
public void executeAsyncTaskPlus(Integer i){
System.out.println("执行异步任务+1: "+(i+1));
}
}
- 运行
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TaskExecutorConfig.class);
AsyncTaskService asyncTaskService = context.getBean(AsyncTaskService.class);
for(int i =0 ;i<10;i++){
asyncTaskService.executeAsyncTask(i);
asyncTaskService.executeAsyncTaskPlus(i);
}
context.close();
}
}
- 结果
执行异步任务: 0
执行异步任务: 2
执行异步任务+1: 3
执行异步任务: 3
执行异步任务+1: 1
执行异步任务: 1
执行异步任务+1: 2
执行异步任务: 5
执行异步任务+1: 5
执行异步任务: 4
执行异步任务+1: 4
执行异步任务: 7
执行异步任务+1: 7
执行异步任务: 6
执行异步任务+1: 6
执行异步任务: 9
执行异步任务+1: 9
执行异步任务: 8
执行异步任务+1: 8
执行异步任务+1: 10
计划任务(Schedule)
- 计划任务执行类
@Service
public class ScheduledTaskService {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
@Scheduled(fixedRate = 5000) //1
public void reportCurrentTime() {
System.out.println("每个5秒执行一次: " + dateFormat.format(new Date()));
}
@Scheduled(cron = "0 26 21 ? * *" ) //2
public void fixTimeExecution(){
System.out.println("指定时间执行: " + dateFormat.format(new Date()));
}
}
- 配置类
@Configuration
@ComponentScan("com.wisely.highlight_spring4.ch3.taskscheduler")
@EnableScheduling //1
public class TaskSchedulerConfig {
}
- 运行
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TaskSchedulerConfig.class);
}
}
- 结果
每个5秒执行一次: 21:25:43
每个5秒执行一次: 21:25:48
每个5秒执行一次: 21:25:53
每个5秒执行一次: 21:25:58
指定时间执行: 21:26:00
每个5秒执行一次: 21:26:03
每个5秒执行一次: 21:26:08
......
条件注解
Profile可以让我们获得不通的Bean,而 @Condition注解可以让我们在一定条件下创建一个特定的Bean。所以在特定条件下空值Bean的创建行为可以让我实现自动配置功能。SpringBoot 中大量的用到了条件注解。
- 判断Windows的条件
public class WindowsCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty("os.name").contains("Windows");
}
}
- 判断Linux的条件
public class LinuxCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty("os.name").contains("Linux");
}
}
- 不同系统下的Bean的类
- 接口
public interface ListService { String showListCmd(); }
- Windows下索要创建的Bean的类
public class WindowsListService implements ListService { public String showListCmd() { return "dir"; } }
- Linux下索要创建的Bean类
public class LinuxListService implements ListService{ public String showListCmd() { return "ls"; } }
- 接口
- 配置类
@Configuration
public class ConditionConifg {
@Bean
@Conditional(WindowsCondition.class) //1
public ListService windowsListService() {
return new WindowsListService();
}
@Bean
@Conditional(LinuxCondition.class) //2
public ListService linuxListService() {
return new LinuxListService();
}
}
- 运行
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConditionConifg.class);
ListService listService = context.getBean(ListService.class);
System.out.println(context.getEnvironment().getProperty("os.name") + "系统下的列表命令为: " + listService.showListCmd());
context.close();
}
}
- 结果
Windows 10系统下的列表命令为: dir
组合注解与元注解
- 实例组合注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration //1
@ComponentScan //2
public @interface WiselyConfiguration {
String[] value() default {}; //3
}
- 演示服务Bean
@Service
public class DemoService {
public void outputResult(){
System.out.println("从组合注解配置照样获得的bean");
}
}
- 新的配置类
@WiselyConfiguration("com.wisely.highlight_spring4.ch3.annotation")
public class DemoConfig {
}
- 运行
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DemoConfig.class);
DemoService demoService = context.getBean(DemoService.class);
demoService.outputResult();
context.close();
}
}
- 结果
从组合注解配置照样获得的bean
@Enable* 注解的工作原理
常见的Enable注解有:
- EnableAspectJAutoProxy:开启对AspectJ自动代码的支持;
- EnableAsync:开启异步方法的支持;
- EnableScheduling:开启计划任务的支持;
- EnableWebMvc:开启Web MVC 的配置支持;
- EnableConfigurationProperties:开启对@ConfigurationProperties注解配置Bean的支持;
- EnableJPARepositories:开启对Spring Data JPA Repository 的支持;
- EnableTransactionManagement:开启注解式事务支持;
- EnableCaching:开启注解式的缓存支持。
整体上,配置方式主要分为三类:
直接导入配置类
如:EnableScheduling
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SchedulingConfiguration.class)
@Documented
public @interface EnableScheduling {
}
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class SchedulingConfiguration {
@Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
return new ScheduledAnnotationBeanPostProcessor();
}
}
依据条件选择配置类
如:EnableAsync
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {
Class<? extends Annotation> annotation() default Annotation.class;
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default Ordered.LOWEST_PRECEDENCE;
}
public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
@Override
@Nullable
public String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {ProxyAsyncConfiguration.class.getName()};
case ASPECTJ:
return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
default:
return null;
}
}
}
动态注册Bean
如:EnableAspectJAutoProxy
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
测试
@RunWith(SpringJUnit4ClassRunner.class) //1
@ContextConfiguration(classes = {TestConfig.class}) //2
@ActiveProfiles("prod") //3
public class DemoBeanIntegrationTests {
@Autowired //4
private TestBean testBean;
@Test //5
public void prodBeanShouldInject(){
String expected = "from production profile";
String actual = testBean.getContent();
Assert.assertEquals(expected, actual);
}
}
Spring Core 有趣的类,可以直接复用啦!
StopWatch
StringUtils
SystemPropertyUtils
StreamUtils
SimpleIdGenerator
SerializationUtils
ObjectUtils
NumberUtils
PatternMatchUtils
MultiValueMap/LinkedMultiValueMap(一键多值Map)
LinkedCaseInsensitiveMap(不区分大小写map)
InstanceFilter
FileSystemUtils
FileCopyUtils
FastByteArrayOutputStream(高性能的ByteArrayOutputStream,思路很清奇)
DefaultPropertiesPersister
CustomizableThreadCreator
ConcurrentReferenceHashMap(与ConcurrentHashMap的区别是可以指定存放对象的引用级别是SOFT、WEAK,ConcurrentHashMap是强引用)
ConcurrencyThrottleSupport (简单的通过synchronized和wati and notify达到控制线程数量的效果,从而实现限流的策略)
CompositeIterator(组合迭代器,也有点意思)
CollectionUtils
ClassUtils
Base64Utils
AntPathMatcher(主要用来做类URLs字符串匹配;)
DataSize(不错不错,可以计算字符串大小,并进行单位换算)
退避策略:固定退避(FixedBackOff)、指数退避(ExponentialBackOff)
Qualifer
https://blog.csdn.net/qq_38257958/article/details/136733938