做單掙錢的網(wǎng)站灰色關(guān)鍵詞排名技術(shù)
Spring使用
資源
Spring 框架內(nèi)部使用 Resource 接口作為所有資源的抽象和訪問接口,在上一篇文章的示例代碼中的配置文件是通過ClassPathResource 進(jìn)行封裝的,ClassPathResource 是 Resource 的一個特定類型的實現(xiàn),代表的是位于 classpath 中的資源。
對不同來源的資源文件 Spring 都提供了相應(yīng)的實現(xiàn):文件(FileSystemResource )、ClassPath資源(ClassPathResource)、URL資源(UrlResource)、InputStream資源(InputStreamResource)、ByteArray資源(ByteArrayResource)等。
注解
宏觀:
①Service
@Service
注解是用來聲明服務(wù)層(Service Layer)組件,通常包含業(yè)務(wù)邏輯,作為數(shù)據(jù)訪問層(Data Access Layer)和控制器(Controller Layer)之間的橋梁。
- 它是一個立即加載的注解,這意味著當(dāng) Spring 應(yīng)用程序啟動時,Spring 容器就會創(chuàng)建標(biāo)注了
@Service
的類的實例。 @Service
是一個特殊類型的@Component
注解。它允許自動檢測通過類路徑掃描,為其創(chuàng)建 Bean 定義并注冊到 Spring 容器中。- 它有助于區(qū)分 Spring 組件的表示層(Controller)、服務(wù)層(Service)和數(shù)據(jù)訪問層(Repository)。
②Controller
用于標(biāo)記一個類作為 Spring MVC 控制器組件??刂破髫?fù)責(zé)處理由 DispatcherServlet 分發(fā)的來自瀏覽器或其他客戶端的 HTTP 請求。這個注解會將類識別為一個 Bean,并注冊到 Spring 應(yīng)用上下文中。
- 通常與
@RequestMapping
或其他基于 HTTP 方法的注解(@GetMapping
,@PostMapping
,@PutMapping
,@DeleteMapping
,@PatchMapping
)配合使用,以定義訪問該控制器方法的 URL 模式和請求類型。 - 允許通過依賴注入引入其他層級的服務(wù)或組件,比如服務(wù)層 (
@Service
) 或數(shù)據(jù)訪問層 (@Repository
)。 - 與視圖技術(shù)(如 Thymeleaf、JSP 等)協(xié)同工作,可以返回 String 類型的視圖名,由視圖解析器進(jìn)一步處理。
- 當(dāng)使用 Spring Boot 和 RESTful Web 服務(wù)時,通常會結(jié)合
@RestController
注解來使用,它是@Controller
和@ResponseBody
的組合體,這意味著控制器的所有響應(yīng)默認(rèn)都會轉(zhuǎn)換成 JSON 或 XML 格式返回給客戶端。
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.ui.Model;@Controller
public class MyController {@RequestMapping("/greet")public String greet(Model model) {model.addAttribute("message", "Hello, World!");return "greeting"; // 返回視圖名稱,通常是一個 HTML 頁面}
}
③Repository
用于標(biāo)識持久層組件(如DAO組件)的特殊化 @Component
注解。當(dāng)你在類上使用 @Repository
注解時,它會告知 Spring 容器該類是一個 Bean,并且用于封裝數(shù)據(jù)訪問異常,將底層數(shù)據(jù)訪問技術(shù)拋出的異常轉(zhuǎn)換為 Spring 的 DataAccessException
。
// 告訴Spring,讓Spring創(chuàng)建一個名字叫“userDao”的UserDaoImpl實例。
@Repository(value="userDao")
public class UserDaoImpl extends BaseDaoImpl<User> {
………
}// 注入userDao,從數(shù)據(jù)庫中根據(jù)用戶Id取出指定用戶時需要用到
@Resource(name = "userDao")
private BaseDao<User> userDao;
④Configuration
@Configuration
是表明某個類是用來作為 bean 定義的源的。被 @Configuration
注解的類通常包含了一個或多個標(biāo)記有 @Bean
注解的方法。Spring 容器會在運行時自動調(diào)用這些方法,將返回對象注冊為容器中的 bean。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Beanpublic MyService myService() {return new MyServiceImpl();}
}
// AppConfig 類被標(biāo)注為 @Configuration,這意味著它可以包含 bean 定義。myService 方法上的 @Bean 注解告訴 Spring,這個方法將返回一個對象,該對象需要被注冊為應(yīng)用程序上下文中的一個 bean。默認(rèn)情況下,bean 的名稱與方法名相同,但可以通過 @Bean 注解的 name 屬性來自定義。// 這種配置方式實現(xiàn)了代碼的模塊化,并且取代了傳統(tǒng)的 XML 配置文件,使得配置更加清晰和類型安全
⑤Resource
@Resource
默認(rèn)按照 by-name 自動裝配,即根據(jù) bean 的名稱進(jìn)行匹配;如果沒有找到與名稱匹配的 bean,則會退回到 by-type 自動裝配(首先嘗試依據(jù)屬性名作為 bean 名稱查找,如果失敗則按類型裝配)。而@Autowired
默認(rèn)按照 by-type 自動裝配。@Resource
所標(biāo)注的自動裝配過程是在 bean 屬性設(shè)置完成之后、初始化方法(如@PostConstruct
注解的方法)之前進(jìn)行的,而@Autowired
則是在構(gòu)造器、字段、setter 方法或其他任意帶有參數(shù)的方法上使用。
import javax.annotation.Resource;
@Component
public class MyComponent {// By name@Resource(name = "myBean")private MyBean myBeanByName;// By type (當(dāng)存在多個相同類型的 bean 時,可能需要指定 name 來避免沖突)@Resourceprivate MyBean myBeanByType;public void doSomething() {// 使用 myBeanByName 和 myBeanByType 完成一些操作...}
}
// @Resource 注解有兩個重要的屬性:name 和 type:
name: 指定要注入的 bean 的名稱。
type: 指定要注入的 bean 的類型。
微觀
① Async:將方法標(biāo)注為異步執(zhí)行
在一個普通的方法或者類中調(diào)用了由 @Async 注解標(biāo)記的方法,那么當(dāng)前線程會立即返回,而實際執(zhí)行的過程會在另外的線程中進(jìn)行,當(dāng)前線程將繼續(xù)執(zhí)行自身的任務(wù)。
@Service
public class MyService {@Autowiredprivate EmailService emailService;@Asyncpublic void sendEmails(List<String> recipients, String content) {for (String recipient : recipients) {emailService.sendEmail(recipient, content);}System.out.println("All emails sent!");}
}
②Autowired:自動裝配依賴的 bean。
@Autowired 注解是 Spring Framework 中的一個依賴注入注解,它可以自動將容器中已經(jīng)創(chuàng)建好的 bean 對象裝配到需要他們的類或者方法中。默認(rèn)先按byType進(jìn)行匹配,如果發(fā)現(xiàn)找到多個bean,則又按照byName方式進(jìn)行匹配,如果還有多個,則報出異常
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class MyComponent {private final Dependency dependency;// 構(gòu)造器注入,如果容器中不存在Dependency類型的Bean,應(yīng)用將無法啟動@Autowired(required = true)public MyComponent(Dependency dependency) {this.dependency = dependency;}// 如果容器中不存在OptionalDependency類型的Bean,則dependency字段將為null,但應(yīng)用依舊會啟動@Autowired(required = false)private OptionalDependency optionalDependency;
}
③Bean:聲明一個需要被 Spring 管理的 bean
@Configuration // 添加了 @Configuration 注解來標(biāo)識這是一個配置類,因此 Spring 容器在掃描時會識別并加載該類。
public class MyConfiguration {@Beanpublic UserDao userDao() {return new JdbcUserDao(dataSource());}@@Bean(“myBean”) // 這樣可以在裝配其他依賴項時方便地引用該 bean 對象。public DataSource dataSource() {// 創(chuàng)建并配置數(shù)據(jù)源對象return new HikariDataSource(config);}
}
在上面的代碼中,我們定義了一個配置類 MyConfiguration,并在其中定義了兩個 bean 對象:userDao() 和 dataSource()。其中 userDao() 方法返回 JdbcUserDao 對象,而 dataSource() 方法返回一個 Hikari 數(shù)據(jù)源對象。這兩個方法都標(biāo)記了 @Bean 注解,這意味著它們會被 Spring 容器掃描到并將創(chuàng)建的對象注冊到容器中。
④Cacheable:增加緩存支持
@Cacheable 是 Spring Framework 中的一個注解,用于實現(xiàn)方法級別的緩存。使用 @Cacheable 注解的方法在調(diào)用時,將會檢查緩存中是否存在與該方法所需參數(shù)相對應(yīng)的緩存項。如果存在,則直接返回緩存結(jié)果,不再執(zhí)行被注解的方法;如果不存在,則執(zhí)行該方法,并將方法的返回結(jié)果添加到緩存中。
@Service
public class UserService {private final UserMapper userMapper;public UserService(UserMapper userMapper) {this.userMapper = userMapper;}@Cacheable(value = "users", key = "#userId")public User getUserById(int userId) {return userMapper.getUserById(userId);}}
⑤ Conditional
Conditional用于根據(jù)特定條件動態(tài)決定是否創(chuàng)建某個 Bean 實例,Spring 還提供了一些預(yù)定義的條件注解,如 @Profile、@ConditionalOnMissingClass、@ConditionalOnProperty 等,它們可以方便地滿足一些常見的判斷場景,減少了編寫自定義條件類的工作量。
@Configuration
public class MyConfiguration {@Bean@Conditional(MyCondition.class)public MyBean myBean() {return new MyBean();}
}public class MyCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// TODO: 自定義條件判斷邏輯return true; // 當(dāng)結(jié)果為 true 時,表示條件成立,按照要求創(chuàng)建 Bean;否則,則不會創(chuàng)建這個 Bean。}
}
使用 @Profile 注解可以確保只有相關(guān)的 beans 在特定的環(huán)境配置下被創(chuàng)建,這樣可以避免在不適合的環(huán)境中運行可能引起沖突或異常的 beans,并有助于維護清晰的環(huán)境特定配置。
@Profile("development")
@Profile("production")根據(jù)設(shè)置系統(tǒng)屬性: -Dspring.profiles.active=development
或者使用環(huán)境變量設(shè)置 SPRING_PROFILES_ACTIVE=development等來切換profile
⑥ConstructorBinding
用于表示在使用基于構(gòu)造器的依賴注入時,應(yīng)該將配置屬性綁定到構(gòu)造器參數(shù)上
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;@ConstructorBinding
@ConfigurationProperties(prefix = "app") //指定哪個前綴的配置屬性應(yīng)被綁定到該類的字段上,Spring Boot 將會查找 app.name 和 app.threadPoolSize 配置項,并通過構(gòu)造器自動注入相應(yīng)的值。
public class AppConfigProperties {private final String name;private final int threadPoolSize;public AppConfigProperties(String name, int threadPoolSize) {this.name = name;this.threadPoolSize = threadPoolSize;}// Getters for the fieldspublic String getName() {return name;}public int getThreadPoolSize() {return threadPoolSize;}
}
⑦ControllerAdvice
@ControllerAdvice 是 Spring MVC 框架中的注解,用于定義一個全局性的異常處理器類。可以對 Controller 層面和全局異常進(jìn)行統(tǒng)一的處理。
@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler({NullPointerException.class, IllegalArgumentException.class}) //當(dāng)捕獲到空指針異?;蛘叻欠▍?shù)異常時,會執(zhí)行這個方法,將異常信息添加到 request 中,并返回 “error” 視圖。public String handleException(Exception e, HttpServletRequest request) {request.setAttribute("error", e);return "error";}
}
⑧CrossOrigin
同源策略阻止一個域下的文檔或腳本與另一個域下的資源進(jìn)行交互。這有助于保護用戶免受惡意網(wǎng)站的攻擊,但也限制了合法的跨源請求。
例如,如果你的頁面在 https://www.example.com 上運行,而嘗試通過 AJAX 請求從 https://api.another-site.com 獲取數(shù)據(jù),這將被默認(rèn)視為跨域請求,并可能遭到瀏覽器的阻止,除非目標(biāo)服務(wù)器明確允許來自原始域的請求。
@RestController
@RequestMapping("/api")
public class ApiController {@CrossOrigin(origins = "http://localhost:8080")@GetMapping("/users/{id}")public User getUserById(@PathVariable Long id) {// ...}
}
⑨EnableAsync
在處理一些 IO 密集型操作時,非常有用
@Configuration
@EnableAsync // @EnableAsync 注解需要與異步方法搭配使用,異步方法需要用 @Async 標(biāo)記。
public class AppConfig {@Beanpublic Executor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(10);executor.setMaxPoolSize(20);executor.setQueueCapacity(30);executor.initialize();return executor;}
}
⑩RequestMapping
@RequestMapping
的專門化版本提供了更簡潔的語法。這些包括 @GetMapping
, @PostMapping
, @PutMapping
, @DeleteMapping
, @PatchMapping
。每個都對應(yīng)于一個 HTTP 方法,使得代碼更加簡潔易讀。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
@RequestMapping("/api")
public class MyController {@GetMapping("/hello") // 等同于 @RequestMapping(value = "/hello", method = GET)@ResponseBodypublic String helloWorld() {return "Hello, World!";}@PostMapping("/submit") // 等同于 @RequestMapping(value = "/submit", method = POST)@ResponseBodypublic String submitForm() {// 方法實現(xiàn)return "Form submitted";}
}
其他
①lazy
@Lazy 是 Spring 框架中的注解之一,它用于控制 Bean 的實例化時間。通過在容器中標(biāo)記一個 Bean 為 @Lazy,可以讓 Spring 容器在第一次使用這個 Bean 時再進(jìn)行實例化。相對應(yīng)的,如果不加 @Lazy 注解,則默認(rèn)情況下 Spring 容器會在啟動時就實例化該 Bean。
@Service
@Lazy // 使用 @Lazy 注解,Spring 容器將在第一次使用 UserService 的實例時才進(jìn)行實例化而不是在啟動時就實例化
public class UserService {// ...
}
②Import
允許我們在一個配置類中引入其他配置類或普通的 Java 類
@Configuration
@Import({DataSourceConfig.class, RedisConfig.class, ServiceUtils.class})
public class AppConfig {// ...
}
// 在創(chuàng)建 Spring ApplicationContext 時,這三個配置類都會被加載并注冊為 Spring 的 bean。
// 可以在 AppConfig 中使用 ServiceUtils 類中的方法或?qū)傩?/span>
③元注解
@Target
:指定注解可以應(yīng)用于 Java 的哪些元素(如類、方法、字段等)。@Retention
:指定注解在什么級別可用(源碼、類文件或運行時)。@Documented
:指定注解是否應(yīng)該被 javadoc 工具記錄。@Inherited
:指定注解是否可以被子類繼承。@Component
:Spring 特有的元注解,用于聲明一個類是 Spring 組件。其它注解如@Service
,@Repository
,@Controller
都是用@Component
注解的例子。
④Valid
在控制器方法的參數(shù)列表中使用 @Valid
( @NotNull、@Min、@Max、@Size、@Email…)注解來實現(xiàn)請求參數(shù)的校驗。
@RestController
@RequestMapping("/users")
public class UserController {@PostMappingpublic User createUser(@Valid @RequestBody User user) {// 保存用戶信息到數(shù)據(jù)庫}// ...
}// 校驗的規(guī)則通常定義在 User 類的屬性上
public class User {@NotBlankprivate String username;@Pattern(regexp = "^[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-zA-Z]{2,}$", message = "Email 格式錯誤")private String email;
}
第三方
-
@Data
@Data
注解是Lombok庫的一部分,非Spring框架本身的一部分。當(dāng)你在一個類上使用@Data
注解,Lombok會自動生成以下代碼:- 所有字段的getter方法
- 所有非最終字段的setter方法
toString()
方法equals()
和hashCode()
方法- 一個包含所有非靜態(tài)、非瞬態(tài)字段的構(gòu)造函數(shù)
這大大減少了樣板代碼的數(shù)量,使得類的定義更加簡潔
-
@Mapper
@Mapper
注解是MyBatis框架的一部分,它主要用于標(biāo)記一個接口作為數(shù)據(jù)庫操作的映射接口。MyBatis通過這個接口關(guān)聯(lián)XML配置文件或者注解中定義的數(shù)據(jù)庫操作。@Mapper public interface UserMapper {User selectUserById(Long id); }// 在Spring Boot項目中,通常還會配合使用@MapperScan注解來指定需要掃描的@Mapper接口所在的包路徑。 @SpringBootApplication @MapperScan("com.example.project.mapper") public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);} }