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&amp;tpl=mn&amp;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>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/>使用百度前必读</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a>&nbsp;京ICP证030173号&nbsp; <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
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring框架使用了多种设计模式来实现其功能和特性。以下是一些Spring框架中常用的设计模式: 1. 单例模式:Spring框架中的Bean默认是单例的,即在整个应用程序中只有一个实例。这样可以提高性能并减少资源消耗。 2. 工厂模式:Spring框架使用工厂模式来创建和管理Bean。通过配置文件或注解,Spring可以根据需要动态地创建和管理Bean的实例。 3. 代理模式:Spring框架使用代理模式来实现AOP(面向切面编程)。通过代理模式,Spring可以在不修改原始类的情况下,为其添加额外的功能,如日志记录、事务管理等。 4. 观察者模式:Spring框架中的事件机制使用了观察者模式。通过定义事件和监听器,Spring可以在特定事件发生时通知相关的监听器执行相应的操作。 5. 模板方法模式:Spring框架中的JdbcTemplate和HibernateTemplate等模板类使用了模板方法模式。这些模板类提供了一些通用的操作方法,开发人员只需要实现特定的回调方法即可。 6. 适配器模式:Spring框架中的适配器模式用于将不同的接口转换为统一的接口。例如,Spring MVC中的HandlerAdapter将不同类型的控制器适配为统一的处理器接口。 7. 依赖注入模式:Spring框架使用依赖注入模式来管理对象之间的依赖关系。通过依赖注入,Spring可以将对象之间的依赖关系外部化,使得对象之间的耦合度降低。 8. 策略模式:Spring框架中的策略模式用于实现不同的算法或行为。例如,Spring Security中的认证策略和授权策略可以根据具体的需求进行配置和替换。 以上是Spring框架中常用的设计模式。通过使用这些设计模式,Spring框架能够提供灵活、可扩展和易于维护的应用程序开发环境。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值