Spring之Aop练习

注意一下,在讲解之前,说明一点:使用Spring AOP,要成功运行起代码,只用Spring提供给开发者的jar包是不够的,请额外上网下载两个jar包:

1、aopalliance.jar

2、aspectjweaver.jar

开始讲解用Spring AOP的XML实现方式,先定义一个接口:

package cn.itcast.oa.service;

public interface HelloWorld {
    void printHelloWorld();

    void doPrint();
}

两个实现类:

package cn.itcast.oa.service.impl;

import cn.itcast.oa.service.HelloWorld;

public class HelloWorldImpl1 implements HelloWorld {
    public void printHelloWorld() {
        System.out.println("Enter HelloWorldImpl1.printHelloWorld()");
    }

    public void doPrint() {
        System.out.println("Enter HelloWorldImpl1.doPrint()");
        return;
    }
}
package cn.itcast.oa.service.impl;

import cn.itcast.oa.service.HelloWorld;

public class HelloWorldImpl2 implements HelloWorld {
    public void printHelloWorld() {
        System.out.println("Enter HelloWorldImpl2.printHelloWorld()");
    }

    public void doPrint() {
        System.out.println("Enter HelloWorldImpl2.doPrint()");
        return;
    }
}

横切关注点,这里面是打印时间:

package cn.itcast.oa.service.impl;

public class TimeHandler {
    public void printTime() {
        System.out.println("CurrentTime = " + System.currentTimeMillis());
    }
}

测试代码:

package cn.itcast.oa.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.itcast.oa.service.HelloWorld;

public class TestAop {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("aop.xml");

        HelloWorld hw1 = (HelloWorld) ctx.getBean("helloWorldImpl1");
        HelloWorld hw2 = (HelloWorld) ctx.getBean("helloWorldImpl2");
        hw1.printHelloWorld();
        System.out.println();
        hw1.doPrint();

        System.out.println();
        hw2.printHelloWorld();
        System.out.println();
        hw2.doPrint();
    }
}

新建aop.xml配置文件,配置文件内容如下:

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

    <bean id="helloWorldImpl1" class="cn.itcast.oa.service.impl.HelloWorldImpl1" />
    <bean id="helloWorldImpl2" class="cn.itcast.oa.service.impl.HelloWorldImpl2" />
    <bean id="timeHandler" class="cn.itcast.oa.service.impl.TimeHandler" />

    <aop:config>
        <aop:aspect id="time" ref="timeHandler">
            <aop:pointcut id="addAllMethod"
                expression="execution(* cn.itcast.oa.service.HelloWorld.*(..))" />
            <aop:before method="printTime" pointcut-ref="addAllMethod" />
            <aop:after method="printTime" pointcut-ref="addAllMethod" />
        </aop:aspect>
    </aop:config>
</beans>

实验结果:

CurrentTime = 1482635730488
Enter HelloWorldImpl1.printHelloWorld()
CurrentTime = 1482635730489

CurrentTime = 1482635730491
Enter HelloWorldImpl1.doPrint()
CurrentTime = 1482635730491

CurrentTime = 1482635730491
Enter HelloWorldImpl2.printHelloWorld()
CurrentTime = 1482635730491

CurrentTime = 1482635730491
Enter HelloWorldImpl2.doPrint()
CurrentTime = 1482635730491

基于Spring的AOP使用其他细节

1、增加一个横切关注点,打印日志,Java类为:

package cn.itcast.oa.service.impl;

public class LogHandler {
    public void LogBefore() {
        System.out.println("Log before method");
    }

    public void LogAfter() {
        System.out.println("Log after method");
    }
}

aop.xml配置文件内容如下:

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

    <bean id="helloWorldImpl1" class="cn.itcast.oa.service.impl.HelloWorldImpl1" />
    <bean id="helloWorldImpl2" class="cn.itcast.oa.service.impl.HelloWorldImpl2" />
    <bean id="timeHandler" class="cn.itcast.oa.service.impl.TimeHandler" />
    <bean id="logHandler" class="cn.itcast.oa.service.impl.LogHandler" />
    <aop:config>
        <aop:aspect id="time" ref="timeHandler">
            <aop:pointcut id="addAllMethod"
                expression="execution(* cn.itcast.oa.service.HelloWorld.*(..))" />
            <aop:before method="printTime" pointcut-ref="addAllMethod" />
            <aop:after method="printTime" pointcut-ref="addAllMethod" />
        </aop:aspect>
        <aop:aspect id="log" ref="logHandler" order="2">
            <aop:pointcut id="printLog"
                expression="execution(* cn.itcast.oa.service.HelloWorld.*(..))" />
            <aop:before method="LogBefore" pointcut-ref="printLog" />
            <aop:after method="LogAfter" pointcut-ref="printLog" />
        </aop:aspect>
    </aop:config>
</beans>

测试代码不变,测试结果如下:

Log before method
CurrentTime = 1482637050240
Enter HelloWorldImpl1.printHelloWorld()
CurrentTime = 1482637050241
Log after method

Log before method
CurrentTime = 1482637050244
Enter HelloWorldImpl1.doPrint()
CurrentTime = 1482637050244
Log after method

Log before method
CurrentTime = 1482637050244
Enter HelloWorldImpl2.printHelloWorld()
CurrentTime = 1482637050245
Log after method

Log before method
CurrentTime = 1482637050246
Enter HelloWorldImpl2.doPrint()
CurrentTime = 1482637050246
Log after method

要想让logHandler在timeHandler前使用有两个办法:

(1)aspect里面有一个order属性,order属性的数字就是横切关注点的顺序

(2)把logHandler定义在timeHandler前面,Spring默认以aspect的定义顺序作为织入顺序
2、我只想织入接口中的某些方法

修改一下pointcut的expression就好了:

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

    <bean id="helloWorldImpl1" class="cn.itcast.oa.service.impl.HelloWorldImpl1" />
    <bean id="helloWorldImpl2" class="cn.itcast.oa.service.impl.HelloWorldImpl2" />
    <bean id="timeHandler" class="cn.itcast.oa.service.impl.TimeHandler" />
    <bean id="logHandler" class="cn.itcast.oa.service.impl.LogHandler" />
    <aop:config>
        <aop:aspect id="time" ref="timeHandler">
            <aop:pointcut id="addAllMethod"
                expression="execution(* cn.itcast.oa.service.HelloWorld.*(..))" />
            <aop:before method="printTime" pointcut-ref="addAllMethod" />
            <aop:after method="printTime" pointcut-ref="addAllMethod" />
        </aop:aspect>
        <aop:aspect id="log" ref="logHandler" order="2">
            <aop:pointcut id="printLog"
                expression="execution(* cn.itcast.oa.service.HelloWorld.do*(..))" />
            <aop:before method="LogBefore" pointcut-ref="printLog" />
            <aop:after method="LogAfter" pointcut-ref="printLog" />
        </aop:aspect>
    </aop:config>
</beans>

表示timeHandler只会织入HelloWorld接口print开头的方法,logHandler只会织入HelloWorld接口do开头的方法

3、强制使用CGLIB生成代理

前面说过Spring使用动态代理或是CGLIB生成代理是有规则的,高版本的Spring会自动选择是使用动态代理还是CGLIB生成代理内容,当然我们也可以强制使用CGLIB生成代理,那就是里面有一个”proxy-target-class”属性,这个属性值如果被设置为true,那么基于类的代理将起作用,如果proxy-target-class被设置为false或者这个属性被省略,那么基于接口的代理将起作用

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页