使用java注解的方式去實現(xiàn)IOC的配置
主要目標:
- 1.學習spring基于java注解的配置方式
- 2.熟悉spring配置注解
進行環(huán)境搭建
- 1.創(chuàng)建maven項目
- 2.引入spring依賴包
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
- 3.創(chuàng)建spring-ioc.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
- 4.創(chuàng)建數(shù)據(jù)庫配置文件db.properties
mysql.username=mall
mysql.password=mall
mysql.url=jdbc:mysql://192.168.1.150:3306/mall
mysql.driver=com.mysql.jdbc.Driver
- 5.創(chuàng)建接口和類
com.learn.controller
UserController
com.learn.service
IUserService
com.learn.service.impl
UserServiceImpl
com.learn.dao
IUserDao
com.learn.dao.impl
UserDaoImpl
com.learn.bean
User
Role
開始學習基礎內容
- 1.對類進行注解標注,將bean注冊到容器中有4種方式:
1.使用xml進行配置bean標簽
2.使用@Component以及相關的標簽進行注解后,使用包掃描方式進行注冊
3.使用@Bean注解
4.使用@Import注解
本例主要使用@Component方式進行注冊bean
@Component,@Controller,@Service,@Repository 四個注解性質基本相同具體如下:
@Component
@Component:spring 注冊組件的注解,@Service,@Controller,@Repository等的注冊功能都是由該注解提供,使用該標注后對應類將注冊到容器中
源碼:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
String value() default "";
}
@Controller
@Controller:控制器纷铣,推薦給controller層添加此注解
源碼
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
@AliasFor(annotation = Component.class)
String value() default "";
}
@Service
@Service:業(yè)務邏輯关炼,推薦給業(yè)務邏輯層添加此注解
源碼
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
@AliasFor(annotation = Component.class)
String value() default "";
}
@Repository
@Repository:倉庫管理,推薦給數(shù)據(jù)訪問層添加此注解
源碼
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
@AliasFor(annotation = Component.class)
String value() default "";
}
從源碼上看@Controller,@Service,@Repository的源碼沒有區(qū)別,只是名稱定義不同,實現(xiàn)功能上三者完全一致,只是表示不同意義,方便開發(fā)者更直觀的定義各個類的意義.
并且能對不同類型的bean進行一個區(qū)別,方便進行操作.
2.給各個類加上@Component相關注解
Controller類加上@Controller注解
例如:
@Controller//將組建添加到容器中--標注為控制器
public class UserController
ServiceImpl相關的類均加上@Service注解
例如:
@Service//配置對象加載到容器中--標注為業(yè)務邏輯類
public class UserServiceImpl implements IUserService
給DaoImpl相關類加上@Repository注解
@Repository//配置對象加載到容器中--標注為數(shù)據(jù)訪問
public class UserDaoImpl implements IUserDao{
給其他需要注冊的類加上@Component注解
例如
@Component
public class User
3.在spring-ioc.xml文件中進行包掃描相關配置,將指定包內的被我們標注要注冊的類均注冊到spring容器中
示例:
<context:component-scan base-package="com.learn" >
</context:component-scan>
//base-package為指定的包路徑
context:component-scan標簽
包含2個子標簽,7個屬性
各個標簽和屬性的意義示例:
<context:component-scan base-package="com.wjx.betalot" <!-- 掃描的基本包路徑 -->
annotation-config="true" <!-- 是否激活屬性注入注解 -->
name-generator="org.springframework.context.annotation.AnnotationBeanNameGenerator" <!-- Bean的ID策略生成器 -->
resource-pattern="**/*.class" <!-- 對資源進行篩選的正則表達式,這邊是個大的范疇见转,具體細分在include-filter與exclude-filter中進行 -->
scope-resolver="org.springframework.context.annotation.AnnotationScopeMetadataResolver" <!-- scope解析器 蒜哀,與scoped-proxy只能同時配置一個 -->
scoped-proxy="no" <!-- scope代理,與scope-resolver只能同時配置一個 -->
use-default-filters="false" <!-- 是否使用默認的過濾器乘客,默認值true -->
>
<!-- 注意:若使用include-filter去定制掃描內容淀歇,要在use-default-filters="false"的情況下,不然會“失效”浪默,被默認的過濾機制所覆蓋 -->
<!-- annotation是對注解進行掃描 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
<!-- assignable是對類或接口進行掃描 -->
<context:include-filter type="assignable" expression="com.wjx.betalot.performer.Performer"/>
<context:include-filter type="assignable" expression="com.wjx.betalot.performer.impl.Sonnet"/>
<!-- 注意:在use-default-filters="false"的情況下,exclude-filter是針對include-filter里的內容進行排除 -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="assignable" expression="com.wjx.betalot.performer.impl.RainPoem"/>
<context:exclude-filter type="regex" expression=".service.*"/>
</context:component-scan>
<context:exclude-filter>和<context:include-filter>兩個標簽的tyep類型決定加載與排除的規(guī)則,具體type類型有如下幾種
/*
annotation:按照注解進行排除碰逸,標注了指定注解的組件不要,expression表示要過濾
的注解
assignable:指定排除某個具體的類阔加,按照類排除,expression表示不注冊的具體類名
aspectj:后面講aop的時候說明要使用的aspectj表達式
custom:定義一個typeFilter,自己寫代碼決定哪些類被過濾掉
regex:使用正則表達式過濾
*/
參考鏈接https://www.cnblogs.com/fightingcoding/p/component-scan.html
4.完成包掃描后可以使用自動注入來獲取bean實例
自動注入實現(xiàn)有兩個標簽分別是
@Autowired
@Resource
@Autowired標簽的使用
使用@Autowired來實現(xiàn)自動注入
·默認優(yōu)先根據(jù)類型去匹配
·如果匹配到多個類型則會按照名字匹配
·如果名又沒有匹配到則會報錯:
1.可以去修改屬性的名字對應bean的名字:userServiceImpl
2.可以去修改Bean的名字對應屬性的名字:@Service("userService")
3.可以通過@Qualifier設置屬性的名字(覆蓋) :@Qualifier("userServiceImpl")
4.可以通過@Primary 設置其中一個Bean為主要的自動注入Bean:@Primary
5.使用泛型作為自動注入限定符
注意:
- 如果只找到一個约急,則直接進行賦值
- 如果沒有找到苗分,則直接拋出異常
- 如果找到多個,那么會按照變量名作為id繼續(xù)匹配
- 匹配上直接進行裝配
- 如果匹配不上則直接報異常
- 當定義@Autowired的required為false時,沒有匹配上是不會報錯的,默認為ture
示例
/**
* @Autowired 也可以寫在構造器上面
* ·默認優(yōu)先根據(jù)參數(shù)類型去匹配
* ·如果匹配到多個類型則會按照參數(shù)名字匹配*/
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
/**
* @Autowired 也可以寫在方法上面
* ·默認優(yōu)先根據(jù)參數(shù)類型去匹配
* ·如果匹配到多個類型則會按照參數(shù)名字匹配
* @Qualifier注解也可以作用在屬性上奴饮,用來被當作id去匹配容器中的對象择浊,如果沒有此注解,那么直接按照類型進行匹配
* @param userService*/
@Autowired
public void createUserSerive(@Qualifier("userServiceImpl")UserService userService){
this.userService=userService;
}
@Autowired源碼
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* <p>Defaults to {@code true}.
*/
boolean required() default true;
}
@Autowired和@Resource都可以自動進行bean注入,但是有一定區(qū)別
1.@Autowired:是spring中提供的注解投剥,@Resource:是jdk中定義的注解担孔,依靠的是java的標準
2.@Autowired默認是按照類型進行裝配吃警,默認情況下要求依賴的對象必須存在啄育,@Resource默認是按照名字進行匹配的,同時可以指定name屬性挑豌。
3.@Autowired只適合spring框架,而@Resource擴展性更好
5.對類的注入設置依賴關系@DependsOn
使用@DependsOn標簽可以設定當前類的注入需要依賴哪些類,將對應類寫入其中后,寫入的類會優(yōu)先于當前類加載到容器中
示例
@Repository//配置對象加載到容器中--標注為數(shù)據(jù)訪問
@DependsOn({"user","role"})
public class UserDaoImpl implements IUserDao
6.將類的注入方式設置為懶加載模式@Lazy
使用@Lazy標簽標注類后,該類將不會自動加載,而是在主動調用后才進行加載
示例
@Repository//配置對象加載到容器中--標注為數(shù)據(jù)訪問
@Lazy//配置對象為懶加載
public class UserDaoImpl implements IUserDao
7.設定bean的作用域使用@Scope標簽
@Scope標簽默認為單例模式,可以根據(jù)情況設置為原型模式(多實例)
示例
@Repository//配置對象加載到容器中--標注為數(shù)據(jù)訪問
@Scope(value = "prototype")
public class UserDaoImpl implements IUserDao
8.設定生命周期控制使用@PostConstruct和@PreDestroy兩個注釋
@PostConstruct設置的是bean初始化時的方法;
@PreDestroy設置的是bean銷毀時調用的方法
示例
// 配置對象初始化時調用的方法
@PostConstruct
public void init(){
System.out.println(" userDaoImpl init");
}
// 配置對象銷毀時的調用方法
@PreDestroy
public void destroy(){
System.out.println("userDaoImpl destroy");
}
總結
1.bean注冊到容器中的方式
2.@Component的細節(jié)和使用
3.包掃描配置方式context:component-scan
4.自動注入@Autowired和@Resource
5.對類的注入設置依賴關系@DependsOn
6.將類的注入方式設置為懶加載模式@Lazy
7.設定bean的作用域使用@Scope標簽
8.設定生命周期@PostConstruct和@PreDestroy