Spring-05 使用註解開發

Spring-05 使用註解開發

使用註解開發

1.項目準備

在spring4以後,想要使用註解形式,必須得要引入aop的包5java

<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.3.3</version>
        </dependency>

在配置文件當中,還得要引入一個context約束git

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

</beans>

2.Bean實現

咱們以前都是使用 bean 的標籤進行bean注入,可是實際開發中,咱們通常都會使用註解!web

一、配置掃描哪些包下的註解spring

<context:component-scan base-package="pojo"/>

二、在指定包下編寫類,增長註解app

// 至關於配置文件中 <bean id="user" class="當前註解的類"/>
@Component("user")
public class User {
    public String name = "zc";
}

3.測試ide

@Test
    public void UserTest(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
        User user = (User) applicationContext.getBean("user");
        System.out.println(user.name);
    }
1

3.屬性注入

3.1 不提供set方法

能夠不提供set方法,直接在屬性名上添加@value(「xxx」)學習

@Component("user")
public class User {
    // 至關於配置文件中 <property name="name" value="秦疆"/>
    @Value("zc")
    public String name;
}

測試結果成功測試

3.1 提供了set方法

若是提供了set方法,在set方法上添加@value(「xxx」)this

@Component("user")
public class User {
    public String name;
    
    @Value("zc")
    public void setName(String name) {
        this.name = name;
    }
}

測試結果成功prototype

4.衍生註解

咱們這些註解,就是替代了在配置文件當中配置步驟而已!更加的方便快捷!

@Component三個衍生註解

爲了更好的進行分層,Spring能夠使用其它三個註解,功能同樣,目前使用哪個功能都同樣。

  • @Controller:web層
  • @Service:service層
  • @Repository:dao層

寫上這些註解,就至關於將這個類交給Spring管理裝配了!

做用域

@scope

  • singleton:默認的,Spring會採用單例模式建立這個對象。關閉工廠 ,全部的對象都會銷燬。
  • prototype:多例模式。關閉工廠 ,全部的對象不會銷燬。內部的垃圾回收機制會回收
@Component("user")
@Scope("prototype")
public class User {
    @Value("zc")
    public String name;
}

總結

XML與註解比較

  • XML能夠適用任何場景 ,結構清晰,維護方便
  • 註解不是本身提供的類使用不了,開發簡單方便

xml與註解整合開發 :推薦最佳實踐

  • xml管理Bean
  • 註解完成屬性注入
  • 使用過程當中, 能夠不用掃描,掃描是爲了類上的註解
<context:annotation-config/>

做用:

  • 進行註解驅動註冊,從而使註解生效
  • 用於激活那些已經在spring容器裏註冊過的bean上面的註解,也就是顯示的向Spring註冊
  • 若是不掃描包,就須要手動配置bean
  • 若是不加註解驅動,則注入的值爲null

5.使用java的方式配置Spring

咱們如今要徹底不使用spring的xml配置,全權交給java來作。

5.1 實體類

@Controller
public class UserT {
        // 屬性的注入
        @Value("zcT")
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    '}';
        }
}

5.2 配置類

@Configuration:本質上也是一個Controller,也會被spring託管,註冊到容器中

@Configuration:表示這是一個配置類,和以前的beans.xml的功能同樣的

@ComponentScan:表示組件的掃描

@import:導入其餘的配置類

@Bean:表示註冊一個bean

@Configuration
@ComponentScan("pojo")
public class MyConfig {
    // 方法的名字便是bean中的id
    // 方法的返回值就是bean中的class
    @Bean
    public UserT getUserT(){
        return new UserT();      // return就是返回要注入到bean中的對象
    }
}

5.3 測試

@Test
    public void UserTTest(){
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        UserT userT = (UserT) context.getBean("getUserT");
        System.out.println(userT.toString());
    }
2

代理模式

爲何要學習代理模式,由於AOP的底層機制就是動態代理。

代理模式:

  • 靜態代理
  • 動態代理

1.靜態代理

角色分析

  • 抽象角色 : 通常使用接口或者抽象類來實現
  • 真實角色 : 被代理的角色
  • 代理角色 : 代理真實角色 ; 代理真實角色後 , 通常會作一些附屬的操做
  • 客戶 : 使用代理角色來進行一些操做

1.1 案例分析

1.1.1 接口類
public interface Rent {
    public void rent();
}
1.1.2 實體類
//房東
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();
    }
    //看房
    public void seeHouse(){
        System.out.println("帶房客看房");
    }
    //收中介費
    public void fare(){
        System.out.println("收中介費");
    }
}
1.1.3 測試實體類
public class Client {
    public static void main(String[] args) {
        // 房東要租房
        Host host = new Host();
        // 中介幫房東
        Proxy proxy = new Proxy(host);
        // 去找中介
        proxy.rent();
    }
}

分析:在這個過程當中,你直接接觸的就是代理類(Proxy),就如同現實生活中的樣子,你看不到房東,可是你依舊經過中介,租到了房東的房子,這就是所謂的代理模式。

靜態代理的好處:

  • 能夠使得咱們的真實角色更加純粹 . 再也不去關注一些公共的事情 .
  • 公共的業務由代理來完成 . 實現了業務的分工 ,
  • 公共業務發生擴展時變得更加集中和方便 .

缺點 :

  • 類多了 , 多了代理類 , 工做量變大了 . 開發效率下降 .

咱們在不改變原來的代碼的狀況下,實現了對原有功能的加強,這是AOP中最核心的思想。

2.動態代理

  • 動態代理的角色和靜態代理的同樣 .

  • 動態代理的代理類是動態生成的,靜態代理的代理類是咱們提早寫好

  • 動態代理分爲兩類 : 一類是基於接口動態代理 , 一類是基於類的動態代理

    • 基於接口的動態代理----JDK動態代理
    • 基於類的動態代理--cglib
    • 如今用的比較多的是 javasist 來生成動態代理
    • 咱們這裏使用JDK的原生代碼來實現

2.1 JDK的動態代理須要瞭解兩個類

核心 : InvocationHandler 和 Proxy

【InvocationHandler:調用處理程序】

Object invoke(Object proxy, 方法 method, Object[] args);
//參數
//proxy - 調用該方法的代理實例
//method -所述方法對應於調用代理實例上的接口方法的實例。方法對象的聲明類將是該方法聲明的接口,它能夠是代理類繼承該方法的代理接口的超級接口。
//args -包含的方法調用傳遞代理實例的參數值的對象的陣列,或null若是接口方法沒有參數。原始類型的參數包含在適當的原始包裝器類的實例中,例如java.lang.Integer或java.lang.Boolean 。

【Proxy : 代理】

//生成代理類
public Object getProxy(){
    return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                                  rent.getClass().getInterfaces(),this);
}

2.2 案例分析

2.2.1 接口類
//抽象角色:租房
public interface Rent {
   public void rent();
}
2.2.2 實體類
//房東
public class Host implements Rent{
    public void rent() {
        System.out.println("出租房子");
    }
}
2.2.3 代理類
public class ProxyInvocationHandler implements InvocationHandler {
    private Rent rent;
    public void setRent(Rent rent) {
        this.rent = rent;
    }
    //生成代理類,重點是第二個參數,獲取要代理的抽象角色!以前都是一個角色,如今能夠代理一類角色
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                rent.getClass().getInterfaces(),this);
    }
    // proxy : 代理類 method : 代理類的調用處理程序的方法對象.
    // 處理代理實例上的方法調用並返回結果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable     {
        //核心:本質利用反射實現!
        Object result = method.invoke(rent, args);
        fare();
        return result;
    }
    //看房
    public void seeHouse(){
        System.out.println("帶房客看房");
    }
    //收中介費
    public void fare(){
        System.out.println("收中介費");
    }
}
2.2.4 測試實體類
public class Client {
    public static void main(String[] args) {
        //真實角色
        Host host = new Host();
        //代理實例的調用處理程序
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setRent(host); //將真實角色放置進去
        Rent proxy = (Rent)pih.getProxy(); //動態生成對應的代理類
        proxy.rent();
    }
}
1

一個動態代理 , 通常代理某一類業務 , 一個動態代理能夠代理多個類,代理的是接口

2.3 動態代理的好處

靜態代理有的它都有,靜態代理沒有的,它也有!

  • 能夠使得咱們的真實角色更加純粹 . 再也不去關注一些公共的事情 .
  • 公共的業務由代理來完成 . 實現了業務的分工 ,
  • 公共業務發生擴展時變得更加集中和方便 .
  • 一個動態代理 , 通常代理某一類業務
  • 一個動態代理能夠代理多個類,代理的是接口!

我的博客爲:
MoYu's Github Blog
MoYu's Gitee Blog

相關文章
相關標籤/搜索