在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>
咱們以前都是使用 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); }
能夠不提供set方法
,直接在屬性名上添加@value(「xxx」)
學習
@Component("user") public class User { // 至關於配置文件中 <property name="name" value="秦疆"/> @Value("zc") public String name; }
測試結果成功測試
若是提供了set方法
,在set方法上添加@value(「xxx」)
this
@Component("user") public class User { public String name; @Value("zc") public void setName(String name) { this.name = name; } }
測試結果成功prototype
咱們這些註解,就是替代了在配置文件當中配置步驟而已!更加的方便快捷!
@Component三個衍生註解
爲了更好的進行分層,Spring能夠使用其它三個註解,功能同樣,目前使用哪個功能都同樣。
寫上這些註解,就至關於將這個類交給Spring管理裝配了!
做用域
@scope
@Component("user") @Scope("prototype") public class User { @Value("zc") public String name; }
總結
XML與註解比較
xml與註解整合開發 :推薦最佳實踐
<context:annotation-config/>
做用:
咱們如今要徹底不使用spring的xml配置,全權交給java來作。
@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 + '\'' + '}'; } }
@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中的對象 } }
@Test public void UserTTest(){ ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); UserT userT = (UserT) context.getBean("getUserT"); System.out.println(userT.toString()); }
爲何要學習代理模式,由於AOP的底層機制就是動態代理。
代理模式:
角色分析
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(); } //看房 public void seeHouse(){ System.out.println("帶房客看房"); } //收中介費 public void fare(){ System.out.println("收中介費"); } }
public class Client { public static void main(String[] args) { // 房東要租房 Host host = new Host(); // 中介幫房東 Proxy proxy = new Proxy(host); // 去找中介 proxy.rent(); } }
分析:在這個過程當中,你直接接觸的就是代理類(Proxy),就如同現實生活中的樣子,你看不到房東,可是你依舊經過中介,租到了房東的房子,這就是所謂的代理模式。
靜態代理的好處:
缺點 :
咱們在不改變原來的代碼的狀況下,實現了對原有功能的加強,這是AOP中最核心的思想。
動態代理的角色和靜態代理的同樣 .
動態代理的代理類是動態生成
的,靜態代理的代理類是咱們提早寫好
的
動態代理分爲兩類 : 一類是基於接口動態代理 , 一類是基於類的動態代理
核心 : 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); }
//抽象角色:租房 public interface Rent { public void rent(); }
//房東 public class Host implements Rent{ public void rent() { System.out.println("出租房子"); } }
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("收中介費"); } }
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(); } }
一個動態代理 , 通常代理某一類業務 , 一個動態代理能夠代理多個類,代理的是接口
靜態代理有的它都有,靜態代理沒有的,它也有!
- 能夠使得咱們的真實角色更加純粹 . 再也不去關注一些公共的事情 .
- 公共的業務由代理來完成 . 實現了業務的分工 ,
- 公共業務發生擴展時變得更加集中和方便 .
- 一個動態代理 , 通常代理某一類業務
- 一個動態代理能夠代理多個類,代理的是接口!