Spring不同裝配方式,代理模式,aop
使用註解開發
-
bean
-
屬性如何注入
//等價於
//@Compoent 元件
@Component
public class User {
//相當於:public String name; @Value("cch2") public void setName(String name) { this.name = name; }
}
-
衍生註解
@Component有幾個衍生註解,我們在web開發中,會按照mvc三層架構分層
- dao 【@Repository】
- service【@Service】
- controller【@Controller】
這四個註解功能都是一樣的,都是代表將某個類註冊到Spring中,裝配Bean
-
自動裝配
- @Autowired:自動裝配,通過型別。名字
如果Autowired不能唯一自動裝配屬性,則需要通過@Qualifier(value = "xxx") - @Nullable 欄位標記了這個註解,說明這個欄位可以為null;
- @Resource: 自動裝配,通過名字。型別
- @Autowired:自動裝配,通過型別。名字
作用域
@Component @Scope("singleton") public class User { //相當於:<property name="name" value="cch2"/> public String name; @Value("cch2") public void setName(String name) { this.name = name; } }
小結
xml與註解:
- xml更加萬能,適用於任何場合 。維護簡單方便
- 註解:不是自己的類使用不了,維護相對複雜
xml與註解最佳實踐:
-
xml用來管理bean;
-
註解只負責完成屬性的注入;
-
我們在使用的過程中,只需要注意一個問題:必須讓註解實效,就需要開啟註解的支援
<context:component-scan base-package="com.king"/> <context:annotation-config/>
使用java的方式配置Spring
實體類
//這裡這個註解的意思,就是說明這個類被Spring接管了,註冊到了容器中 @Component public class User { private String name; public String getName() { return name; } @Value("xsb")//屬性注入值 public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } }
配置檔案
//這個也會被Spring容器託管,註冊到容器中,他本來就是@Component,
// @Configuration 代表這是一個配置類,就和我們之前看到的bean.xml
@Configuration
@ComponentScan("com.kua.pojo")
@Import(MyConfig2.class)
public class MyConfig {
//註冊一個bean,就相當於我們之前寫的一個bean標籤
//這個方法的名字,就相當於標籤中的id屬性
//這個方法的返回值,就相當於bean標籤中的class屬性
@Bean
public User getUser(){
return new User();//就是返回要注入到bean的物件
}
}
測試類
public class MyTest {
public static void main(String[] args) {
//如果完全使用了配置類的方式去做,我們就只能通過ApplicationConfig 上下文來獲取容器,通過配置類的class物件載入
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User user = context.getBean("getUser", User.class);
System.out.println(user.getName());
}
}
這種純java的配置方式,在SpringBoot中隨處可見
代理模式
SpringAOP的底層就是代理模式
代理模式的分類:
- 靜態代理
角色分析:
- 抽象角色:一般會使用介面或者抽象類來決定
- 真實角色:被代理的角色
- 代理角色:代理真實物件,代理真實角色後,我們一般會 做一些附屬操作
- 客戶:訪問代理物件的人
程式碼步驟:
-
介面
public interface Rent {
public void rent();
} -
真實角色
//房東
public class Host implements Rent{public void rent() { System.out.println("房東要出租房子"); } }
-
代理角色
public class Proxy implements Rent{
private Host host;public Proxy() { } public Proxy(Host host) { this.host = host; } public void rent() { host.rent(); seeHouse(); fare(); ht(); System.out.println("中介代你向房東租房"); } //看房 public void seeHouse(){ System.out.println("中介帶你看房"); } //收中介費 public void fare(){ System.out.println("收中介費"); } //籤租賃合同 public void ht(){ System.out.println("籤租賃合同"); } }
-
客戶端訪問代理角色
public class Client {
public static void main(String[] args) {
//房東要出租房子
Host host = new Host();
//代理,中介棒房東出租房子,但是呢。同時代理角色一般有一些附屬操作
Proxy proxy = new Proxy(host);
//你不用面對房東,直接找中介租房即可
proxy.rent();
}
}
代理模式的好處:
- 可以使真實角色的操作更加純粹,不用去關注一些公共的業務。
- 公共業務就交給代理物件去做,實現業務的分工。
- 公共業務發生擴充套件的時候,方便集中管理。
缺點:
- 一個真實角色就會產生一個代理角色;程式碼量會翻倍,導致開發效率變低
動態代理
- 動態代理和靜態代理角色一樣
- 動態代理的代理類是動態生成的,不是我們直接寫好的
- 動態代理分成兩大類:基於介面的動態代理,基於類的動態代理
- 基於介面---JDK動態代理
- 基於類:cglib
- 位元組碼檔案實現:javassist
需要了解兩個類:Proxy:代理,InvocationHandler:呼叫處理程式
動態代理的好處:
- 可以使真實角色的操作更加純粹,不用去關注一些公共的業務。
- 公共業務就交給代理物件去做,實現業務的分工。
- 公共業務發生擴充套件的時候,方便集中管理。
- 一個動態代理類代理的是一個介面,一般對應的是一類業務。
- 一個動態代理類可以代理多個類只要是實現了同一個介面即可。
使用spring實現aop
【重點】使用aop注入,需要匯入一個依賴包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
方式一:使用Spring的API介面實現
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--註冊bean-->
<bean id="userService" class="com.xxx.service.UserServiceImpl"/>
<bean id="log" class="com.xxx.log.Log"/>
<bean id="afterLog" class="com.xxx.log.AfterLog"/>
<!--方式一:使用原生Spring API介面-->
<!-- 配置aop:需要匯入aop的約束-->
<aop:config>
<!--切入點:expression:表示式。execution(要執行的位置 * * * * *)-->
<aop:pointcut id="pointcut" expression="execution(* com.xxx.service.UserServiceImpl.*(..))"/>
<!--執行環繞增加-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
</beans>
方式二:自定義AOP實現【切面定義】
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--註冊bean-->
<bean id="userService" class="com.xxx.service.UserServiceImpl"/>
<bean id="log" class="com.xxx.log.Log"/>
<bean id="afterLog" class="com.xxx.log.AfterLog"/>
<!--方式二:自定義類-->
<bean id="diy" class="com.xxx.diy.DiyPointCut"/>
<aop:config>
<!-- 自定義切面,ref要引用的類 -->
<aop:aspect ref="diy">
<!--切入點-->
<aop:pointcut id="point" expression="execution(* com.xxx.service.UserServiceImpl.*(..))"/>
<!--通知-->
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
</beans>
方式三:使用註解方式實現AOP
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--註冊bean-->
<bean id="userService" class="com.xxx.service.UserServiceImpl"/>
<bean id="log" class="com.xxx.log.Log"/>
<bean id="afterLog" class="com.xxx.log.AfterLog"/>
<!-- 方式三:使用註解實現AOP-->
<bean id="annotationPointCut" class="com.xxx.diy.AnnotationPointCut"/>
<!--開啟註解支援 JDK(預設 proxy-target-class="false") cglib(proxy-target-class="false)-->
<aop:aspectj-autoproxy/>
</beans>