1. 程式人生 > >Aop第一節

Aop第一節

aop使用 lte 流程 iso 公司 user 集合 如何使用 攔截器

什麽是AOP

AOP(Aspect-OrientedProgramming,面向方面編程),可以說是OOP(Object-Oriented Programing,面向對象編程)的補充和完善。OOP引入封裝、繼承和多態性等概念來建立一種對象層次結構,用以模擬公共行為的一個集合。當我們需要為分散的對象引入公共行為的時候,OOP則顯得無能為力。也就是說,OOP允許你定義從上到下的關系,但並不適合定義從左到右的關系。例如日誌功能。日誌代碼往往水平地散布在所有對象層次中,而與它所散布到的對象的核心功能毫無關系。對於其他類型的代碼,如安全性、異常處理和透明的持續性也是如此。這種散布在各處的無關的代碼被稱為橫切(cross-cutting)代碼,在OOP設計中,它導致了大量代碼的重復,而不利於各個模塊的重用。

而AOP技術則恰恰相反,它利用一種稱為“橫切”的技術,剖解開封裝的對象內部,並將那些影響了多個類的公共行為封裝到一個可重用模塊,並將其名為“Aspect”,即方面。所謂“方面”,簡單地說,就是將那些與業務無關,卻為業務模塊所共同調用的邏輯或責任封裝起來,便於減少系統的重復代碼,降低模塊間的耦合度,並有利於未來的可操作性和可維護性。AOP代表的是一個橫向的關系,如果說“對象”是一個空心的圓柱體,其中封裝的是對象的屬性和行為;那麽面向方面編程的方法,就仿佛一把利刃,將這些空心圓柱體剖開,以獲得其內部的消息。而剖開的切面,也就是所謂的“方面”了。然後它又以巧奪天功的妙手將這些剖開的切面復原,不留痕跡。

使用“橫切”技術,AOP把軟件系統分為兩個部分:核心關註點和橫切關註點。業務處理的主要流程是核心關註點,與之關系不大的部分是橫切關註點。橫切關註點的一個特點是,他們經常發生在核心關註點的多處,而各處都基本相似。比如權限認證、日誌、事務處理。Aop 的作用在於分離系統中的各種關註點,將核心關註點和橫切關註點分離開來。正如Avanade公司的高級方案構架師Adam Magee所說,AOP的核心思想就是“將應用程序中的商業邏輯同對其提供支持的通用服務進行分離。”

實現AOP的技術,主要分為兩大類:一是采用動態代理技術,利用截取消息的方式,對該消息進行裝飾,以取代原有對象行為的執行;二是采用靜態織入的方式,引入特定的語法創建“方面”,從而使得編譯器可以在編譯期間織入有關“方面”的代碼。

AOP使用場景

AOP用來封裝橫切關註點,具體可以在下面的場景中使用:

Authentication 權限

Caching 緩存

Context passing 內容傳遞

Error handling 錯誤處理

Lazy loading 懶加載

Debugging  調試

logging, tracing, profiling and monitoring 記錄跟蹤 優化 校準

Performance optimization 性能優化

Persistence  持久化

Resource pooling 資源池

Synchronization 同步

Transactions 事務

AOP相關概念

方面(Aspect):一個關註點的模塊化,這個關註點實現可能另外橫切多個對象。事務管理是J2EE應用中一個很好的橫切關註點例子。方面用spring的 Advisor或攔截器實現。

連接點(Joinpoint): 程序執行過程中明確的點,如方法的調用或特定的異常被拋出。

通知(Advice): 在特定的連接點,AOP框架執行的動作。各種類型的通知包括“around”、“before”和“throws”通知。通知類型將在下面討論。許多AOP框架包括Spring都是以攔截器做通知模型,維護一個“圍繞”連接點的攔截器鏈。Spring中定義了四個advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice

切入點(Pointcut): 指定一個通知將被引發的一系列連接點的集合。AOP框架必須允許開發者指定切入點:例如,使用正則表達式。 Spring定義了Pointcut接口,用來組合MethodMatcher和ClassFilter,可以通過名字很清楚的理解, MethodMatcher是用來檢查目標類的方法是否可以被應用此通知,而ClassFilter是用來檢查Pointcut是否應該應用到目標類上

引入(Introduction): 添加方法或字段到被通知的類。 Spring允許引入新的接口到任何被通知的對象。例如,你可以使用一個引入使任何對象實現 IsModified接口,來簡化緩存。Spring中要使用Introduction, 可有通過DelegatingIntroductionInterceptor來實現通知,通過DefaultIntroductionAdvisor來配置Advice和代理類要實現的接口

目標對象(Target Object): 包含連接點的對象。也被稱作被通知或被代理對象。POJO

AOP代理(AOP Proxy): AOP框架創建的對象,包含通知。 在Spring中,AOP代理可以是JDK動態代理或者CGLIB代理。

織入(Weaving): 組裝方面來創建一個被通知對象。這可以在編譯時完成(例如使用AspectJ編譯器),也可以在運行時完成。Spring和其他純Java AOP框架一樣,在運行時完成織入。

如何使用Spring AOP

可以通過配置文件或者編程的方式來使用Spring AOP。

配置可以通過xml文件來進行,大概有四種方式:

1. 配置ProxyFactoryBean,顯式地設置advisors, advice, target等

2. 配置AutoProxyCreator,這種方式下,還是如以前一樣使用定義的bean,但是從容器中獲得的其實已經是代理對象

3. 通過<aop:config>來配置

4. 通過<aop: aspectj-autoproxy>來配置,使用AspectJ的註解來標識通知及切入點

也可以直接使用ProxyFactory來以編程的方式使用Spring AOP,通過ProxyFactory提供的方法可以設置target對象, advisor等相關配置,最終通過 getProxy()方法來獲取代理對象

具體使用的示例可以google. 這裏略去

Spring AOP代理對象的生成

技術分享

public class User {
    private Integer id; // 用戶ID
    private String username; // 用戶名
    private String password; // 密碼
    private String email; // 電子郵件

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}
public interface IUserDAO {
    
    public void save(User user);
}
public class UserDAOImpl implements IUserDAO {
    public void save(User user) {
        System.out.println("save success!");
    }
}
public interface IUserService {
    public  void save2(User user);
}
public class UserServiceImpl implements IUserService {
    private IUserDAO dao;
    public void save2(User user) {
        dao.save(user);
    }

    public IUserDAO getDao() {
        return dao;
    }

    public void setDao(IUserDAO dao) {
        this.dao = dao;
    }
}
public class LoggerBeforeAdvice implements MethodBeforeAdvice {
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("======我傲驕==================");
    }
}

技術分享

<?xml version="1.0" encoding="UTF-8"?>
<beans 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 "
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns="http://www.springframework.org/schema/beans">

    <bean id="dao" class="cn.bdqn.aop02.dao.UserDAOImpl"/>

    <bean id="service" class="cn.bdqn.aop02.service.UserServiceImpl">

        <property name="dao" ref="dao"></property>

    </bean>

    <bean class="cn.bdqn.aop02.aop.LoggerBeforeAdvice" id="beforeAdvice"/>

    <aop:config>

        <aop:pointcut id="mypointcut" expression="execution(public void save2(cn.bdqn.aop02.entity.User))"/>

        <aop:advisor pointcut-ref="mypointcut" advice-ref="beforeAdvice"/>

    </aop:config>
</beans>

測試

 @Test
    public void tesst04() {
        ApplicationContext cxt=new ClassPathXmlApplicationContext("applicationContextaop.xml");
        IUserService service =(IUserService) cxt.getBean("service");
        User user=new User();
        service.save2(user);
    }

Aop第一節