【SpringBoot】@Configration與@Bean的使用
文章目錄
一.前言
Spring Boot 推薦使用 java 配置完全代替 XML 配置,java 配置是通過 @Configration 和 @Bean 註解實現的。
- @Configration:作用在
類
上,宣告當前類是一個配置類
,相當於 Spring 中的一個 XML配置檔案,可理解為用Spring的xml配置檔案裡的<beans>標籤。
- @Bean:作用在
方法
上,宣告當前方法的返回值是一個Bean
,相當於Spring的XML配置檔案中的<bean>標籤
二.使用Java配置方式基礎Shiro框架
這些xml配置和java程式碼大概瞄一下就行了,重點是要了解用xml配置檔案
與Java配置
方式區別
例如: 在spring專案中我們整合第三方的框架如shiro會在spring.xml配置檔案中進行配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 提供shiro的相關配置,簡單的說,就是把shiro.ini裡的內容搬到這個xml檔案裡面來了,只是寫法不同-->
<!--首先宣告自定義URL匹配過濾器 --> <!--TODO:新增-->
<bean id="urlPathMatchingFilter" class="com.oyjp.filter.URLPathMatchingFilter"/>
<!-- 配置shiro的過濾器工廠類,id- shiroFilter要和我們在web.xml中配置的過濾器一致 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 呼叫我們配置的許可權管理器 -->
<property name="securityManager" ref="securityManager"/>
<!-- 配置我們的登入請求地址 -->
<property name="loginUrl" value="/login"/>
<!-- 如果您請求的資源不再您的許可權範圍,則跳轉到/403請求地址 -->
<property name="unauthorizedUrl" value="/unauthorized"/>
<!-- 退出 -->
<property name="filters">
<util:map>
<entry key="logout" value-ref="logoutFilter"/>
<entry key="url" value-ref="urlPathMatchingFilter" /> <!--TODO:新增-->
</util:map>
</property>
<!-- 許可權配置 -->
<property name="filterChainDefinitions">
<value>
<!-- anon表示此地址不需要任何許可權即可訪問 -->
/login=anon
/index=anon
/static/**=anon
<!-- 只對業務功能進行許可權管理,許可權配置本身不需要沒有做許可權要求,這樣做是為了不讓初學者混淆:大概的意思就是所有 /config的請求都不進行許可權校驗 -->
/config/**=anon
/doLogout=logout
/404=anon
/500=anon
/favicon.ico=anon
/unauthorized=anon
<!--所有的請求(除去配置的靜態資源請求或請求地址為anon的請求)都要通過登入驗證,如果未登入則跳到/login -->
<!--/** = authc-->
<!--所有的請求(除去配置的靜態資源請求或請求地址為anon的請求)都要通過過濾器url TODO:新增 -->
/** = url
</value>
</property>
</bean>
<!-- 退出過濾器 -->
<bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">
<property name="redirectUrl" value="/index"/>
</bean>
<!-- 會話ID生成器 -->
<bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/>
<!-- 會話Cookie模板 關閉瀏覽器立即失效 -->
<bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="sid"/>
<property name="httpOnly" value="true"/>
<property name="maxAge" value="-1"/>
</bean>
<!-- 會話DAO -->
<bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
<property name="sessionIdGenerator" ref="sessionIdGenerator"/>
</bean>
<!-- 會話驗證排程器,每30分鐘執行一次驗證 ,設定會話超時及儲存 -->
<bean name="sessionValidationScheduler"
class="org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler">
<property name="interval" value="1800000"/>
<property name="sessionManager" ref="sessionManager"/>
</bean>
<!-- 會話管理器 -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<!-- 全域性會話超時時間(單位毫秒),預設30分鐘 -->
<property name="globalSessionTimeout" value="1800000"/>
<property name="deleteInvalidSessions" value="true"/>
<property name="sessionValidationSchedulerEnabled" value="true"/>
<property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>
<property name="sessionDAO" ref="sessionDAO"/>
<property name="sessionIdCookieEnabled" value="true"/>
<property name="sessionIdCookie" ref="sessionIdCookie"/>
<property name="sessionIdUrlRewritingEnabled" value="false" /> <!--去掉URL中的JSESSIONID-->
</bean>
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="databaseRealm"/>
<property name="sessionManager" ref="sessionManager"/>
</bean>
<!-- 相當於呼叫SecurityUtils.setSecurityManager(securityManager) -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
<property name="arguments" ref="securityManager"/>
</bean>
<!-- 密碼匹配器 -->
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="md5"/> <!--加密演算法-->
<property name="hashIterations" value="2"/> <!--加密次數-->
<property name="storedCredentialsHexEncoded" value="true"/>
</bean>
<!-- DatabaseRealm 真正做登入驗證和授權的地方-->
<bean id="databaseRealm" class="com.oyjp.realm.DatabaseRealm">
<property name="credentialsMatcher" ref="credentialsMatcher"/>
</bean>
<!-- 保證實現了Shiro內部lifecycle函式的bean執行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
</beans>
使用@Configration+@Bean可以將原本在xml
中的配置,轉移到Java程式碼中進行配置,被
@Configration修飾的類稱為"配置類"
- 使用 @Configration 註解將該類
ShiroConfiguration
宣告為一個配置類。 - 在方法上新增
@Bean
註解則會往Spring 容器
中預設
新增一個名為方法名首字母小寫
的Bean,該 Bean 即為方法的返回值。
@Configuration
public class ShiroConfiguration {
/**
* ShiroFilterFactoryBean 處理攔截資原始檔問題。
* 注意:單獨一個ShiroFilterFactoryBean配置是或報錯的,因為在
* 初始化ShiroFilterFactoryBean的時候需要注入:SecurityManager
* <p>
* Filter Chain定義說明
* 1、一個URL可以配置多個Filter,使用逗號分隔
* 2、當設定多個過濾器時,全部驗證通過,才視為通過
* 3、部分過濾器可指定引數,如perms,roles
*/
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
System.out.println("ShiroConfiguration.shirFilter()");
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必須設定 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 如果不設定預設會自動尋找Web工程根目錄下的"/login.jsp"頁面
shiroFilterFactoryBean.setLoginUrl("/login");
// 登入成功後要跳轉的連結
shiroFilterFactoryBean.setSuccessUrl("/index");
//未授權介面;
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
//攔截器.
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//自定義攔截器
Map<String, Filter> customisedFilter = new HashMap<>();
customisedFilter.put("url", getUrlPathMatchingFilter());
//配置對映關係
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/index", "anon");
filterChainDefinitionMap.put("/static/**", "anon");
filterChainDefinitionMap.put("/config/**", "anon");
filterChainDefinitionMap.put("/doLogout", "logout");
filterChainDefinitionMap.put("/**", "url");
shiroFilterFactoryBean.setFilters(customisedFilter);
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* 用於例項化自定義URL匹配過濾器
* URLPathMatchingFilter 並沒有用@Bean管理起來。 原因是Shiro的bug, 這個也是過濾器,ShiroFilterFactoryBean 也是過濾器,當他們都出現的時候,預設的什麼anno,authc,logout過濾器就失效了。所以不能把他宣告為@Bean。
*/
public UrlPathMatchingFilter getUrlPathMatchingFilter() {
return new UrlPathMatchingFilter();
}
/**
* 例項化安全管理器並設定DatabaseRealm(真正做登入驗證和授權的地方)
*/
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//設定realm.
securityManager.setRealm(getDatabaseRealm());
return securityManager;
}
@Bean
public DatabaseRealm getDatabaseRealm() {
DatabaseRealm myShiroRealm = new DatabaseRealm();
myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return myShiroRealm;
}
/**
* 例項化憑證匹配器
* (由於我們的密碼校驗交給Shiro的SimpleAuthenticationInfo進行處理了所以我們需要修改下doGetAuthenticationInfo中的程式碼; )
*/
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//雜湊演算法:這裡使用MD5演算法;
hashedCredentialsMatcher.setHashAlgorithmName("md5");
//雜湊的次數,比如雜湊兩次,相當於 md5(md5(""));
hashedCredentialsMatcher.setHashIterations(2);
return hashedCredentialsMatcher;
}
/**
* 開啟shiro aop註解支援.
* 使用代理方式;所以需要開啟程式碼支援;
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
/**
* 例項化LifecycleBeanPostProcessor 保證實現了Shiro內部lifecycle函式的bean執行
*/
@Bean
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
}
三.@Configuration
3.1.@Configuration作用
- @Configuration底層是含有
@Component
,所以@Configuration 具有和@Component
的作用。 - @Configuration 用於定義
配置類
,可理解為Spring的xml配置檔案裡面的<beans>
標籤。 - @Configration 標註的類不能是
final
型別 - @Configration 標註類中可以宣告
一個或多個 @Bean
方法
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
String value() default "";
}
@Configuration標註在類上
,相當於把該類作為spring的xml配置檔案中的<beans>
作用為
:配置spring容器(應用上下文)
@Configuration
public class TestConfiguration {
public TestConfiguration() {
System.out.println("TestConfiguration容器啟動初始化。。。");
}
}
相當於
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd" default-lazy-init="false">
</beans>
3.2.@Configuration使用
@Configration
標註的類中可以宣告多個@Bean
方法,並且 Bean 與 Bean 之間是可以有依賴關係的
。
如果一個 bean 的依賴其他 bean,可以注入方式有:
- 直接呼叫對配置類中
依賴Bean的方法
- 在
形參
上使用@Qualifier("beanName")
通過Bean的名字
注入例項 - 在
形參
上使用@Autowired
通過Bean的型別
注入例項
相關Bean
@Data
public class TestBean {
private String username;
private String url;
private String password;
}
@Data
public class TestBean2{
//省略類結構,和TestBean一樣
}
@Data
public class TestBean3{
//省略類結構,和TestBean一樣
}
@Data
public class TestBean4{
//省略類結構,和TestBean一樣
}
@Configuration
public class TestConfiguration {
@Bean
public TestBean testBean() {
TestBean testBean = new TestBean();
testBean.setUsername("admin");
testBean.setPassword("123456");
testBean.setUrl("www.testBean.com");
return testBean;
}
/**
* 使用@Qualifier通過Bean的名字注入例項
*/
@Bean
public TestBean2 testBean2(@Qualifier("testBean") TestBean testBean) {
TestBean2 testBean2 = new TestBean2();
testBean2.setUsername(testBean.getUsername());
testBean2.setPassword(testBean.getPassword());
testBean2.setUrl("www.TestBean2.com");
return testBean2;
}
/**
* 使用@Autowired通過Bean的型別注入例項
*/
@Bean
public TestBean3 testBean3(@Autowired TestBean2 testBean2) {
TestBean3 testBean3 = new TestBean3();
testBean3.setUsername(testBean2.getUsername());
testBean3.setPassword(testBean2.getPassword());
testBean3.setUrl("www.TestBean3.com");
return testBean3;
}
/**
* 呼叫Bean的方法獲取依賴Bean
*/
@Bean
public TestBean4 testBean4() {
TestBean testBean = testBean();//獲取TestBean例項
TestBean4 testBean4 = new TestBean4();
testBean4.setUsername(testBean.getUsername());
testBean4.setPassword(testBean.getPassword());
testBean4.setUrl("www.testBean4.com");
return testBean4;
}
}
四.@Bean
4.1.@Bean作用
@Bean標註在方法上(返回某個例項的方法)
,等價於spring的xml配置檔案
中的<bean>
,
作用為
:註冊bean物件
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
@AliasFor("name")
String[] value() default {};
@AliasFor("value")
String[] name() default {};
/** @deprecated */
@Deprecated
Autowire autowire() default Autowire.NO;
boolean autowireCandidate() default true;
String initMethod() default "";
String destroyMethod() default "(inferred)";
}
- name: 指定bean的名字,並且可以接受一個陣列,配置多個name,預設採用的是
"方法名" + "首字母小寫"
的命名方式- initMethod: 初始化Bean時執行的方法名
- destoryMethod: 銷燬Bean時執行的方法名
或者使用通過@PostConstruct 和 @PreDestroy 方法 實現初始化和銷燬bean之前進行的操作 。
配置類
@Configuration
public class TestConfiguration {
public TestConfiguration() {
System.out.println("TestConfiguration容器啟動初始化。。。");
}
// @Bean註解註冊bean,同時可以指定初始化和銷燬方法
@Bean(initMethod = "init",destroyMethod = "destroy")
@Scope("prototype")//每次從Spring容器獲取都會新建一個TestBean 物件
public TestBean testBean() {
TestBean testBean = new TestBean();
testBean.setUsername("admin");
testBean.setPassword("123456");
testBean.setUrl("www.baidu.com");
return testBean;
}
}
要被註冊到Spring容器的Bean
@Data
public class TestBean {
private String username;
private String url;
private String password;
//Bean初始化方法
public void init() {
System.out.println("TestBean 初始化。。。");
}
//Bean銷燬方法
public void destroy() {
System.out.println("TestBean 銷燬。。。");
}
}
上述操作相當於例項化TestBean ,並交給Spring容器管理
注:
- @Bean標註的
方法
,如果沒有指定bean的名稱
,預設採用的是 “方法名” + "首字母小寫"的命名方式 - @Bean註解
預設作用域為單例singleton作用域
,可通過@Scope("prototype")
設定為原型作用域; - @Bean的作用是註冊bean物件,我們也可以使用
@Component、@Controller、@Service、@Repository
等註解註冊bean(在需要註冊的類上加註解
),然後配置@ComponentScan
註解進行自動掃描。
4.2.指定@Bean別名
Bean 名稱
預設情況下 Bean 名稱就是方法名,比如下面 Bean 名稱便是 myBean
@Bean
public MyBean myBean() {
return new MyBean();
}
@Bean 註解支援設定別名。
@Bean("myBean")
public MyBean myBean() {
return new MyBean();
}
@Bean 註解支援設定多個別名。
@Bean({"myBean1","myBean2"})
public MyBean myBean() {
return new MyBean();
}
4.3.@Bean 與其他註解一起使用
@Bean 註解常與 @Scope、@Lazy,@DependsOn 和 @Primary
註解一起使用:
- @Profile :可以在不同環境載入不同的Bean。如: 開發環境和生產環境載入不同的資料來源Bean
- @Scope :將 Bean 的作用域從單例改變為指定的作用域
@Scope("prototype ") :每次獲取 Bean 的時候會有一個新的例項
- @Lazy :只有在預設單例作用域的情況下才有實際效果
- @DependsOn :在當前 Bean 建立之前需要先建立其他 Bean,可以控制Bean的載入順序,
- @Primayr: 當一種型別的Bean,可能會有幾種不同的實現類,可以使用@Primary,讓Sping容器預設注入某一個例項
4.3.@Bean初始化和銷燬的回撥
通過 @Bean 註解的initMethod
和 destrodMethod
數學可以Bean 在初始化和銷燬時會呼叫哪個方法
public class MyBean {
public void init() {
System.out.println("MyBean開始初始化...");
}
public void destroy() {
System.out.println("MyBean銷燬...");
}
}
@Bean(initMethod="init", destroyMethod="destroy")
public MyBean myBean() {
return new MyBean();
}
Spring Boot不是Spring的加強版,所以@Configuration和@Bean同樣可以用在
普通的spring專案
中。
相關文章
- Springboot中的Bean作用域Spring BootBean
- SpringBoot原始碼解析-Bean的載入與自動化配置Spring Boot原始碼Bean
- SpringBoot自動裝配原理之Configuration以及@Bean註解的使用Spring BootBean
- SpringBoot基礎篇之重名Bean的解決與多例項選擇Spring BootBean
- springboot~AutoConfigureAfter如何控制Bean的注入順序Spring BootBean
- ElasticSearch與SpringBoot的整合與JPA方法的使用ElasticsearchSpring Boot
- SpringBoot基礎篇Bean之條件注入@Condition使用姿勢Spring BootBean
- SpringBoot基礎篇Bean之條件注入之註解使用Spring BootBean
- SpringBoot中@PropertySource和@ImportResource以及@BeanSpring BootImportBean
- SpringBoot(14)—註解裝配BeanSpring BootBean
- SpringBoot 學習之 No bean named ‘xxx’ availableSpring BootBeanAI
- springboot @RequestBody bean 物件 為空問題Spring BootBean物件
- springboot使用jpa啟動報錯consider defining a bean of type '*.*.**Repository' in your configuration....Spring BootIDEBean
- SpringBoot CLI安裝與使用Spring Boot
- Java SpringBoot 中,動態執行 bean 物件中的方法JavaSpring BootBean物件
- springboot bean的迴圈依賴實現 原始碼分析Spring BootBean原始碼
- springboot註解實現非同步呼叫時no bean of type TaskExecutor and no bean named 'taskExecutor' eitherSpring Boot非同步Bean
- 使用Mockito修改Bean的依賴MockitoBean
- springboot~mybatis-pagehelper原理與使用Spring BootMyBatis
- SpringBoot系列之攔截器注入Bean的幾種姿勢Spring BootBean
- SpringBoot基礎篇Bean之動態註冊Spring BootBean
- Spring核心——Bean的定義與控制SpringBean
- 27、EJB與JAVA BEAN的區別?JavaBean
- 如何正確控制springboot中bean的載入順序總結Spring BootBean
- @FeignClient @Resource 無法注入Bean Springboot無法啟動clientBeanSpring Boot
- SpringBoot AOP的使用Spring Boot
- SpringBoot整合Junit單元測試找不到bean報錯:expected at least 1 bean which qualifies as autowire candidateSpring BootBeanAST
- SpringBoot中根據屬性動態註冊Spring BeanSpring BootBean
- Spring中ref local=""與ref bean=""的區別SpringBean
- Spring中與bean有關的生命週期SpringBean
- SpringBoot 中 JPA 的使用Spring Boot
- springboot中RedisTemplate的使用Spring BootRedis
- SpringBoot的@Conditional使用 - reflectoringSpring Boot
- SpringBoot(三)_controller的使用Spring BootController
- 使用jstl無法遍歷bean中的集合JSBean
- Spring基礎使用(一)--------IOC、Bean的XML方式SpringBeanXML
- Springboot啟動了哪些bean?這兩種方式可以獲取Spring BootBean
- Bean的一生(Bean的生命週期)Bean