SpringBoot5-spring高階話題-組合註解與元註解,@Enable*註解的工作原理,測試
一:組合註解與元註解
從spring2開始,為了響應JDK1.5推出的註解供暖,spring開始大量加入註解來替代xml配置。spring的註解主要用來配置和注入bean,以及AOP相關的配置(@Transactional)。隨著註解的大量使用,尤其相同的多個註解用到各個類或方法中,會相當繁瑣。這就是所謂的樣板程式碼,是spring設計的原則中要消除的程式碼。
所謂元註解其實就是可以註解到別的註解上的註解,被註解的註解稱之為組合註解,組合註解具備註解其上的元註解的功能。spring的很多註解都可以作為元註解,而且spring本身已經有很多組合註解,如@Configuration就是一個組合@Component註解,表明這個類其實也是一個Bean。
前面我們大量使用了@Configuration和@ComponentScan註解到配置類上,下面我們把這兩個註解組成一個組合註解。
示例:
package jack.ch3.annotation; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import java.lang.annotation.*; /** * Created by jack on 2017/7/15. * 組合註解 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration //組合@Configuration元註解 @ComponentScan //組合@ComponentScan元註解 public @interface WiselyConfiguration { //覆蓋value引數 String [] value() default {}; }
演示服務的Bean:
package jack.ch3.annotation;
import org.springframework.stereotype.Service;
/**
* Created by jack on 2017/7/15.
*/
@Service
public class DemoService {
public void outputResult(){
System.out.println("從組合註解配置照樣獲取的Bean");
}
}
配置類:
package jack.ch3.annotation; /** * Created by jack on 2017/7/15. */ //使用@WiselyConfiguration組合註解替代@Configuration和@ComponentScan @WiselyConfiguration("jack.ch3.annotation") public class DemoConfig { }
測試程式碼如下:
package jack.ch3.annotation;
import jack.ch3.conditional.ConditionConfig;
import jack.ch3.conditional.ListServer;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* Created by jack on 2017/7/15.
*/
public class MainTest12 {
public static void main(String [] args){
//AnnotationConfigApplicationContext作為spring容器,接受一個配置類作為引數
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DemoConfig.class);
DemoService demoService = context.getBean(DemoService.class);
demoService.outputResult();
context.close();
}
}
執行程式,輸出如下:
D:\java\jdk1.8.0_111\bin\java -Didea.launcher.port=7535 "-Didea.launcher.bin.path=D:\programmingsoftware\IDEA\JetBrains\IntelliJ IDEA 2016.3.2\bin" -Dfile.encoding=UTF-8 -classpath "D:\java\jdk1.8.0_111\jre\lib\charsets.jar;D:\java\jdk1.8.0_111\jre\lib\deploy.jar;D:\java\jdk1.8.0_111\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_111\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_111\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_111\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_111\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_111\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_111\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_111\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_111\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_111\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_111\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_111\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_111\jre\lib\javaws.jar;D:\java\jdk1.8.0_111\jre\lib\jce.jar;D:\java\jdk1.8.0_111\jre\lib\jfr.jar;D:\java\jdk1.8.0_111\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_111\jre\lib\jsse.jar;D:\java\jdk1.8.0_111\jre\lib\management-agent.jar;D:\java\jdk1.8.0_111\jre\lib\plugin.jar;D:\java\jdk1.8.0_111\jre\lib\resources.jar;D:\java\jdk1.8.0_111\jre\lib\rt.jar;E:\webworkspace\IdeaProjects\springstudy1\target\classes;C:\Users\wj\.m2\repository\org\springframework\spring-context\4.1.6.RELEASE\spring-context-4.1.6.RELEASE.jar;C:\Users\wj\.m2\repository\org\springframework\spring-beans\4.1.6.RELEASE\spring-beans-4.1.6.RELEASE.jar;C:\Users\wj\.m2\repository\org\springframework\spring-core\4.1.6.RELEASE\spring-core-4.1.6.RELEASE.jar;C:\Users\wj\.m2\repository\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;C:\Users\wj\.m2\repository\org\springframework\spring-expression\4.1.6.RELEASE\spring-expression-4.1.6.RELEASE.jar;C:\Users\wj\.m2\repository\org\springframework\spring-aop\4.1.6.RELEASE\spring-aop-4.1.6.RELEASE.jar;C:\Users\wj\.m2\repository\aopalliance\aopalliance\1.0\aopalliance-1.0.jar;C:\Users\wj\.m2\repository\org\aspectj\aspectjrt\1.8.5\aspectjrt-1.8.5.jar;C:\Users\wj\.m2\repository\org\aspectj\aspectjweaver\1.8.5\aspectjweaver-1.8.5.jar;C:\Users\wj\.m2\repository\commons-io\commons-io\2.3\commons-io-2.3.jar;C:\Users\wj\.m2\repository\javax\annotation\jsr250-api\1.0\jsr250-api-1.0.jar;D:\programmingsoftware\IDEA\JetBrains\IntelliJ IDEA 2016.3.2\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain jack.ch3.annotation.MainTest12
七月 15, 2017 3:27:09 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
資訊: Refreshing org.spring[email protected]5d099f62: startup date [Sat Jul 15 15:27:09 CST 2017]; root of context hierarchy
從組合註解配置照樣獲取的Bean
七月 15, 2017 3:27:09 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
資訊: Closing org.spring[email protected]5d099f62: startup date [Sat Jul 15 15:27:09 CST 2017]; root of context hierarchy
Process finished with exit code 0
二:@Enable*註解的工作原理
在前面我們通過@EnableAspectJAutoProxy開啟對AspectJ自動代理的支援。@EnableAsync開啟非同步方法的支援
@EnableScheduling開啟計劃任務的支援
@EnableWebMvc開啟Web MVC的配置支援
@EnableConfigurationProperties開啟對@ConfigurationProperties註解配置Bean的支援。
@EnableJpaRepositor開啟對Spring Data JPA Repository的支援
@EnableTransactionManagement開啟註解事務的支援
@EnableCaching開啟註解式的快取支援
通過簡單的@Enable*來開啟一項功能的支援,從而避免自己配置大量的程式碼,大大降低了使用難度。下面看看實現該功能的原理。
通過觀察這些@Enable*註解的原始碼,我們發現所有的註解都有一個@Import註解,@Import是用來匯入配置類的,這也意味著這些自動開啟的實現其實是匯入一些自動配置的bean。這些匯入的配置方式主要分為以下三種類型。
1,第一類:直接匯入配置類
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.scheduling.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
import org.springframework.scheduling.annotation.SchedulingConfiguration;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({SchedulingConfiguration.class})
@Documented
public @interface EnableScheduling {
}
直接匯入配置類SchedulingConfiguration,這個類註解了@Configuration,且註冊了一個scheduledAnnotationProcessor的Bean,原始碼如下:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.scheduling.annotation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor;
@Configuration
public class SchedulingConfiguration {
public SchedulingConfiguration() {
}
@Bean(
name = {"org.springframework.context.annotation.internalScheduledAnnotationProcessor"}
)
@Role(2)
public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
return new ScheduledAnnotationBeanPostProcessor();
}
}
2,第二類:依據條件選擇配置類
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.scheduling.annotation;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Import;
import org.springframework.scheduling.annotation.AsyncConfigurationSelector;
@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 2147483647;
}
AsyncConfigurationSelector通過條件來選擇需要匯入的配置類,AsyncConfigurationSelector的根介面為ImportSelector,這個介面需重寫selectImports方法,在此方法內進行事先條件判斷。此例中,若adviceMode為PORXY,則返回ProxyAsyncConfiguration這個配置類;若activeMode為ASPECTJ,則返回AspectJAsyncConfiguration配置類,原始碼如下:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.scheduling.annotation;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.AdviceModeImportSelector;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.ProxyAsyncConfiguration;
public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME = "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
public AsyncConfigurationSelector() {
}
public String[] selectImports(AdviceMode adviceMode) {
switch(null.$SwitchMap$org$springframework$context$annotation$AdviceMode[adviceMode.ordinal()]) {
case 1:
return new String[]{ProxyAsyncConfiguration.class.getName()};
case 2:
return new String[]{"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration"};
default:
return null;
}
}
}
3,第三類:動態註冊Bean
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.AspectJAutoProxyRegistrar;
import org.springframework.context.annotation.Import;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
}
AspectJAutoProxyRegistrar實現了ImportBeanDefinitionRegistar介面,ImportBeanDefinitionRegistrar的作用是在執行時自動新增Bean到已有的配置類,通過重寫方法
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if(enableAJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
}
其中AnnotationMetadata引數用來獲得當前配置類上的註解;BeanDefinitionRegistry引數用來註冊Bean。原始碼如下:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.context.annotation;
import org.springframework.aop.config.AopConfigUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
AspectJAutoProxyRegistrar() {
}
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if(enableAJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
}
}
三:測試
測試是開發中不可缺少的部分,單元測試只針對當前開發的類和方法進行測試,可以簡單通過模擬依賴來實現,對執行環境沒有依賴。spring通過Spring TestContex Framework對整合測試提供頂級支援。它不依賴於特定的測試框架,既可使用Junit,也可以使用TestNG。
基於Maven構建的專案結構預設有關於測試的目錄:src/test/java(測試程式碼),src/test/resources(測試資源),區別於src/main/java(專案原始碼),src/main/resources(專案資源)
Spring提供了一個SpringJUnit4ClassRunner類,它提供了Spring TestContext Framework的功能。通過@ContextConfiguration來配置ApplicationContext,通過@ActiveProfiles確定活動的profile。
在使用了Spring測試後,我們前面例子的執行部分都可以用spring測試來檢驗功能能否正常運作。
下面對簡單配置的Application Context和在測試中注入Bean做演示。
1,準備
增加Spring測試的依賴包到Maven
<!--Spring test 支援-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
業務程式碼:
在src/main/java下的原始碼:
package jack.ch3.test;
/**
* Created by jack on 2017/7/16.
*/
public class TestBean {
private String content;
public TestBean(String content) {
this.content = content;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
配置類:
package jack.ch3.test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
/**
* Created by jack on 2017/7/16.
*/
@Configuration
public class TestConfig {
@Bean
@Profile("dev")
public TestBean devTestBean(){
return new TestBean("from development profile");
}
@Bean
@Profile("prod")
public TestBean prodTestBean(){
return new TestBean("from production profile");
}
}
測試:
在src/test/java下的程式碼:
package jack.ch3.test;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* Created by jack on 2017/7/16.
*/
@RunWith(SpringJUnit4ClassRunner.class)//SpringJUnit4ClassRunner在JUnit環境下提供Spring TestContext Framework的功能
@ContextConfiguration(classes = {TestConfig.class}) //@ContextConfiguration用來載入配置ApplicationContext,其中classes屬性用來載入配置類
@ActiveProfiles("prod") //@ActiveProfiles用來宣告活動的profile
public class DemoBeanIntegrationTests {
@Autowired //可使用普通的@Autowired注入Bean
private TestBean testBean;
@Test //測試程式碼,通過JUnit的Assert來校驗是否和預期一致
public void prodBeanShouldInject(){
String expected = "from production profile";
String actual = testBean.getContent();
Assert.assertEquals(expected,actual);
}
}
測試結果如下:
將
@ActiveProfiles("prod")改為
@ActiveProfiles("dev")
將採用開發配置的bean
到目前為止,maven中pom.xml的內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jack</groupId>
<artifactId>springstudy1</artifactId>
<version>1.0-SNAPSHOT</version>
<!--定義屬性-->
<properties>
<java.version>1.8</java.version>
</properties>
<!--新增依賴-->
<dependencies>
<!--新增spring框架依賴包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!--spring的aop支援-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!--aspectj支援-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.5</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.5</version>
</dependency>
<!--增加commons-io可簡化檔案相關操作-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.3</version>
</dependency>
<!--增加JSR250支援-->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>
<!--Spring test 支援-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
</dependencies>
<!--新增外掛-->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
相關推薦
SpringBoot5-spring高階話題-組合註解與元註解,@Enable*註解的工作原理,測試
一:組合註解與元註解 從spring2開始,為了響應JDK1.5推出的註解供暖,spring開始大量加入註解來替代xml配置。spring的註解主要用來配置和注入bean,以及AOP相關的配置(@Transactional)。隨著註解的大量使用,尤其相同的多個註
spring boot組合註解與元註解
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration @ComponentScan public @interface WiselyConfiguration {
【Spring】Spring高階話題[email protected]***註解的工作原理
@EnableAspectJAutoProxy @EnableAspectJAutoProxy註解 啟用Aspect自動代理 <aop:aspectj-autoproxy/> 開啟對AspectJ自動代理的支援。 在用到AOP的
SpringBoot4-spring高階話題-spring aware,多執行緒,計劃任務,條件註解@Conditional
一:Spring Aware 1,點睛 spring的依賴注入的最大亮點就是你所有的Bean對Spring容器的存在是沒有意識的,即你可以將你的容器替換成別的容器,如Google Guice,這時Bean之間的耦合度很低。 但是在實際專案中,你不可避免的要
Spring高階話題-多執行緒-TaskExecutor
分析 在Spring中,通過任務執行器,也就是TaskExecutor來實現多執行緒和併發程式設計。 使用ThreadPoolTaskExecutor可實現一個基於執行緒池的TaskExecutor。 而實際開發中任務一般是非阻礙的,也就是非非同步的,所以
JavaEE開發的顛覆者:Spring Boot實戰 學習筆記4--Spring高階話題
SpringAware 可呼叫Spring所提供的資源 多執行緒 配置類 /** * 多執行緒和併發程式設計 */ @Configuration @ComponentScan("com.wisely.highlight_spring4_idea.ch3.t
【Spring】Spring高階話題-計劃任務[email pr
進行本示例的演示,需要先配置好Maven和spring哦、 見: http://blog.csdn.net/qq_26525215/article/details/53010442 分析 要實現計劃任務,首先通過在配置類註解@EnableScheduling來開
【Spring】Spring高階話題-多執行緒-TaskExecutor
分析 在Spring中,通過任務執行器,也就是TaskExecutor來實現多執行緒和併發程式設計。 使用ThreadPoolTaskExecutor可實現一個基於執行緒池的TaskExecutor。 而實際開發中任務一般是非阻礙的,也就是非非同步
USB HOST與 USB OTG的區別及工作原理
在SmartQ 7上面,同時存在USB HOST與 USB OTG兩個介面,我想問一下,這兩個介面有什麼區別麼?我怎麼認為HOST屬於是多餘呢? 麻煩高手解答,感激不盡!!! 零 USB背景知識 USB是一種資料通訊方式,也是一種資料匯流排,而且是最複雜的匯流排之一。&
spark核心程式設計,spark基本工作原理與RDD
Spark2.0筆記 spark核心程式設計,spark基本工作原理與RDD 1. Spark基本工作原理 2. RDD以及其特點 3. 什麼是Spark開發 1.Spark基本工作原理 2. RDD以及其特點 3. 什麼是Spark開發 spark核心程
Eureka的工作原理以及它與ZooKeeper的區別 Eureka的工作原理以及它與ZooKeeper的區別
Eureka的工作原理以及它與ZooKeeper的區別 1、Eureka 簡介: Eureka 是 Netflix 出品的用於實現服務註冊和發現的工具。 Spring Cloud 集成了 Eureka,並提供了開箱即用的支援。其中, Eureka 又可細分為 Eur
spring工作原理,Spring MVC的前端控制器模式
Spring MVC的前端控制器模式 spring mvc也是依賴servlet,所以spring mvc的請求處理是從一個servlet開始,這個servlet就是DispatcherServlet。 前端控制器模式(Front Controller Pa
資料庫事務隔離級別與鎖機制的實現----不是針對PostgreSQL,而是普遍的原理,來自網際網路,有刪節
文章來自原文連結: 版權歸原作者所有,有刪節,只保留對我理解有幫助的部分。 事務隔離級別通過鎖的實現機制兩個鎖排他鎖: 被加鎖的物件只能被持有鎖的事務讀取和修改,其他事務無法在該物件上加其他鎖,也不能讀取和修改該物件。 共享鎖: 被加鎖的物件可以被持鎖事務讀取
編譯器與解釋器的區別和工作原理
架構 平臺 感覺 -i 調用 詞法 繼續 python 自動 這篇教程,我們一起來了解編譯器和解釋器的工作原理,這對我們提升能力很重要。 我一直認為概念或理論知識是非常重要的,讓我們能夠將很多模糊的認知關聯起來,變得更加清楚,從而打開視野,上升到新的層次。 但是,一般來
Spring MVC的工作原理,我們來看看其原始碼實現
前言 開心一刻 晚上陪老丈人吃飯,突然手機響了,我手賤按了擴音……哥們:快出來喝酒!哥幾個都在呢!我:今天不行,我現在陪老丈人吃飯呢。哥們:那你抓緊喝,我三杯白酒,把我岳父放倒了才出來的,你也快點。看著我老丈人的臉,我不知道該怎麼回了……
Spring註解與Java元註解小結
spa package param style 值範圍 描述 tro ret 類型 註解 Annotation 基於註解的開發,使得代碼簡潔,可讀性高,簡化的配置的同時也提高了開發的效率,尤其是SpringBoot的興起,隨著起步依賴和自動配置的完善,更是將基於註解的開發推
Spring高級話題[email protected]***註解的工作原理
sso metadata bool logs tcl task ota -c ann 出自:http://blog.csdn.net/qq_26525215 @EnableAspectJAutoProxy @EnableAspectJAutoProxy註解 激活Aspe
spring,mybatis事務管理配置與@Transactional註解使用[轉]
exception true throws r.java 存在 隔離 enc prot 底層 spring,mybatis事務管理配置與@Transactional註解使用 概述事務管理對於企業應用來說是至關重要的,即使出現異常情況,它也可以保證數據的一致性。Sprin
Spring@Autowired註解與自動裝配
arp details auto 反射機制 java -i etc str spi 1 配置文件的方法 我們編寫spring 框架的代碼時候。一直遵循是這樣一個規則:所有在spring中註入的bean 都建議定義成私有的域變量。並且要配套寫上 get 和 set方法
spring,mybatis事務管理配置與@Transactional註解使用
抽象 classname 初始 for batis 時間限制 自動提交 data second spring,mybatis事務管理配置與@Transactional註解使用 概述事務管理對於企業應用來說是至關重要的,即使出現異常情況,它也可以保證數據的一致性。Spring