Spring_Aop的xml和注解的使用


動態代理:

    目的:在不改變源代碼的情況下,對方法進行增強!
    
    動態代理又分為兩種:
    1.第一個就是基於接口的動態代理,他是由jdk提供的
    2.基於子類的動態代理:cglib提供的:要想使用基於子類的動態代理:就必須得導入cglib的jar包
    
    特性:被代理對象的任意方法
    

Spring_aop:總結
aop(Aspect Oriented Programming) :面向切面編程

切面:相對於業務主線的額外的功能模塊
在不改變程序源代碼的情況下對方法進行增強

aop的底層原理就是動態代理
    aop的底層他會自動的根據代碼,選擇是使用基於還是使用子類的動態代理!
    
    使用aop進行編程有啥好處呢?
        1.簡化業務代碼
        2.維護簡單
        
        Aop相關術語
        Joinpoint(連接點):執行的方法
        pointcut(切入點):被增強的方法
        Advice(通知/增強):就是額外的功能模塊
            前置通知
            后置通知
            異常通知
            最終通知
            環繞通知
            Aspect(切面):
                對那個方法進行怎樣的增強
        學習Aop重點關注的事情是啥呢?
        1.重點關注的是一個一個的額外的功能模塊
        2.aop的配置
第三 spring Aop的開發流程
            定義一個切面類
            普通的Java類,在這個類中通過一個一個的方法對目標對象進行增強
            
            2.配置Aop
                在xml里面配置文件中aop
                i.將切面類交給spring管理
                
                ii.聲明Aop配置
                <aop:config>
                iii.定義切入點
                aop:pointcut
                iiii.定義通知類型
                <aop:aspect ref = "切面類的引用">
                    前置通知
                    <aop:before method="切面類的方法名" pointcut-ref="切入點表達式是引用"/>
                    后置通知<aop:afterRunturning method="切面類的方法名" pointcut-ref="切入點表達式是引用"/>
                    異常通知<aop:after-throwing method="切面類的方法名" pointcut-ref="切入點表達式是引用"/>
                    最終通知<aop:after method="切面類的方法名" pointcut-ref="切入點表達式是引用"/>
                    注意:異常通知只有出現了異常了 才會有通知
                </aop:aspect>
                基於注解的Aop配置(結合xml)
            1.將切面類交給spring管理
            2.使用注解的形式代替xml中的aop的配置
            3.使用注解配置spring的ioc或者aop的時候都需要開啟對注解的支持!
            
            注意:使用注解配置Aop和xml配置Aop在后置通知的時候,有一些差別!
            注解的配置:是最后執行后置通知!
            
            純注解配置Aop
            1.聲明配置類
            2.開啟對ioc的支持
            3.開啟對aop注解的支持
            @EnableAspectJAutoProxy
            
開發步驟以及代碼的解釋
        <!-- 將切面類交給spring管理 -->
        <bean id="logger" class="cn.itcast.utils.Logger"></bean>
        
        <!-- 聲明AOP配置:需要使用aop的命名空間(必須導入aop的約束)
        aop:config : 聲明aop配置
     -->
    <aop:config>
    
    <!-- 定義切入點:定義被增強的方法
            expression : execution(類的修飾符 返回值 包名.包名...類名.方法名(參數列表))
            1.類的修飾符可以省略 :返回值 包名.包名...類名.方法名(參數列表)
            2.返回值可以使用*號代替:標識任意返回值都可以
            3.包名可以使用*號代替,一個包需要一個*
            4.包名..代表此包   以及   此包的任意子包
            5.類名可以使用*代替,代表任意類
            6.方法名可以使用*代理,代表任意方法
            7.參數類別可以使用..代表任意參數
            
            **** 此寫法 * *..*.*(..) 不推薦
            
         -->
        <aop:pointcut expression="execution(* cn.itcast.service.impl..*.*(..))" id="pt"/>
        
        
        
        <!-- 配置切面
                aop:aspect
                    ref:被spring管理的切面類的引用
        -->
        <aop:aspect ref="logger">
        
        
            <!-- 定義通知的類型
                aop:before  定義前置通知
                    method:切面類中定義的方法名
                    pointcut-ref:切入點表達式是引用
            -->
            <aop:before method="before" pointcut-ref="pt"/>
            
            這是xml里面的配置
            
注解配合xml使用代碼以及解釋
    <!-- 開啟對spring ioc的支持 -->
    <context:component-scan base-package="cn.itcast"></context:component-scan>
    
    <!-- 開啟對aop注解的支持 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
    
    /*
 * 切面類:
 *         對目標對象進行日志部分的增強是通過此類中的方法來實現
 * 在切面類上
 *         定義切面類
 * 在切面方法上
 *         使用注解的形式定義通知類型
 */
@Component("logger")
@Aspect
public class Logger {//這是配置到類上的

/**
     * 抽取切入點表達式
     *         @Pointcut:定義切入點表達式
     *             這個注解需要配置到方法上,這個方法是一個空的方法
     *             應用這個切入點表達式的時候,只需要引入方法名就可以了
     *             但是需要  方法名()   需要加括號
     */
    @Pointcut(value="execution(* cn.itcast.service.impl..*.*(..))")//注意:類名前面那兩個點改成一個點也是可以的
    @Pointcut(value="execution(* cn.itcast.service.impl.*.add*(..))")//這是指定對那個方法進行增強
    public void pt() {//定義一個通用的,這樣前置通知,后置通知等等用的時候只需要引用這個方法名就行了
        
    }
    
    /**
     * 定義前置通知
     *     @Before :
     *         value : 可以是一個切入點表達式,也可以是一個切入點表達式的引用
     *             切入點表達式    
     */
    @Before("pt()")
    public void before() {
        System.out.println("進入方法之前打印日志");
    }
    
            
    *這是注解配置xml的方法

純注解的配置方式


/*
 * 切面類:
 *         對目標對象進行日志部分的增強是通過此類中的方法來實現
 * 在切面類上
 *         定義切面類
 * 在切面方法上
 *         使用注解的形式定義通知類型
 */
@Component("logger")
@Aspect
public class Logger {
    
    /**
     * 抽取切入點表達式
     *         @Pointcut:定義切入點表達式
     *             這個注解需要配置到方法上,這個方法是一個空的方法
     *             應用這個切入點表達式的時候,只需要引入方法名就可以了
     *             但是需要  方法名()   需要加括號
     */
    @Pointcut(value="execution(* cn.itcast.service.impl..*.*(..))")
    public void pt() {
        
    }
    
    /**
     * 定義前置通知
     *     @Before :
     *         value : 可以是一個切入點表達式,也可以是一個切入點表達式的引用
     *             切入點表達式    
     */
    @Before("pt()")
    public void before() {
        System.out.println("進入方法之前打印日志");
    }
    
    
    @AfterReturning("pt()")
    public void afterReturning() {
        System.out.println("執行目標方法得到返回值后打印日志");
    }
    
    @AfterThrowing("pt()")
    public void afterThrowing() {
        System.out.println("拋出異常打印日志");
    }
    
    @After("pt()")
    public void after() {
        System.out.println("在最終代碼塊中打印日志");
    }
    
    //5.定義環繞通知
    /**
     * 環繞通知是spring提供的一種
     *     讓程序員手動指定要執行的增強方法的一種手段,
     * 在此方法中可以根據需求自定義以上4中通知類型
     *     在環繞通知中,需要手動去調用被增強的方法
     *     借助spring提供的一個對象ProceedingJoinPoint
     *             此對象中有一個方法,可以調用被增強的方法
     *         pjp.proceed();執行被增強的的方法
     *             eg:動態代理中的,method.invoke();
     *
     * @throws Throwable
     */
    @Around("execution(* cn.itcast.service.impl..*.*(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("前置通知");
        Object obj = null;
        try{
            obj = pjp.proceed();
            System.out.println("后置通知");
        }catch(Exception e){
            System.out.println("異常通知");
            e.printStackTrace();
        }finally{
            System.out.println("最終通知");
        }
        return obj;
    }
}







/spring的配置類
//在配置類中替換xml配置文件中的剩余配置項

/**
 * 1。聲明配置類
 * 2。開啟對ioc的支持
 * 3。開啟對AOP注解的支持
 *         @EnableAspectJAutoProxy
 *
 */
@Configuration
@ComponentScan(basePackages="cn.itcast")
@EnableAspectJAutoProxy
public class Config {

}





    public class Client {

    public static void main(String[] args) {
        //測試ioc的配置
        //ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        ApplicationContext ac = new AnnotationConfigApplicationContext(Config.class);
        
        CustomerService customerService = (CustomerService)ac.getBean("customerService");
        customerService.updateCustomer();
    }
}
        這是純注解的方式
        
        Aop事物案例
        
        @Component("logger")
@Aspect
public class Logger {
    
    @Pointcut(value="execution(* cn.crm.service.impl..*.*(..))")
    public void pt(){
        
    }
    
    @Around(value="pt()")
    public Object tx(ProceedingJoinPoint pjp) throws Throwable{
        Session session = null;
        Transaction tx = null;
        
        Object obj = null;
        
        try {
            session = HibernateUtils.getCurrentSession();
            tx = session.beginTransaction();
            
            obj = pjp.proceed();
            
            tx.commit();
            
        } catch (Exception e) {
            System.out.println("出現異常了");
            tx.rollback();
            
        }finally {
            
            System.out.println("最終執行的代碼");
            
        }
        
        return obj;
        
    }
    

}


    public class Client{
        public static void main(String[] args) {
        
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        
        CustomerService customerService = (CustomerService)ac.getBean("customerService");
        
        
        Customer customer = new Customer();
        
        customer.setCustName("hello");
        
        customerService.addCustomer(customer);
    }
        
    }

        xml配置:
         <context:component-scan base-package="cn.crm"></context:component-scan>
        
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
        
        
        
        這是一個小小的Aop的事物案例,
當然Spring也提供了事物的支持,但是今天只做了個Aop的事物,希望對大家有幫助


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM