征服Spring

Spring AOP 代理

2019-06-20  本文已影响17人  希希里之海

Spring AOP 代理

1. Spring AOP 增强类型

AOP 联盟为通知 Advice 定义了 org.aopalliance.aop.Interface.Advice

Spring 按照通知 Advice 在目标类方法的连接点位置,可以分为 5 类


2. Spring AOP 切面类型


3. Advisor 切面案例 (xml 配置)

ProxyFactoryBean 常用可配置属性:

举个例子:

applicationContext.xml

<!-- 1. 配置目标类 -->
<bean id="studentDao" class="com.test.aop.demo3.StudentDaoImpl" />

<!-- 2. 前置通知类型 -->
<bean id="myBeforeAdvice" class="com.test.aop.demo3.MyBeforeAdvice" />

<!-- 3. Spring 的 AOP 产生代理对象 -->
<bean id="studentDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    <!-- 配置目标类 -->
    <property name="target" ref="studentDao" />
    <!-- 实现的接口 -->
    <property name="proxyInterfaces" value="com.test.aop.demo3.StudentDao" />
    <!-- 采用拦截的名称 -->
    <!-- 注意这个地方使用 value -->
    <property name="interceptorNames" value="myBeforeAdvice" />
    <!-- 默认使用 jdk 动态代理,使用下列语句更改为 CGLib 生成代理 -->
    <property name="optimize" value="true" />
</bean>

通知类:

public class MyBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("前置增强========");
    }
}

4. 演示(Advisor 方式)

首先要使用 AOP,我们需要导入两个包:

<dependency>
    <groupId>aopalliance</groupId>
    <artifactId>aopalliance</artifactId>
    <version>1.0</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>4.2.4.RELEASE</version>
</dependency>

然后定义接口和实现类,再定义一个通知类(如前置通知),然后我们在 xml 文件中配置目标类和通知类,利用 Spring AOP 产生代理(通过bean配置),具体可参考上述例子,使用注解的方式在测试类中导入增强后的 bean:studentDaoProxy。

具体代码:SpringDemo3.demo1()


5. PointcutAdvisor 切点切面

使用普通 Advice 作为切面,将对目标类所有方法进行拦截,不够灵活,在实际开发中常采用带有切点的切面。

常用 PointcutAdvisor 实现类

这里以 JdkRegexpMethodPointcut 为例:

applicationContext.xml

<!-- 配置目标类 -->
<bean id="customerDao" class="com.test.aop.demo4.CustomerDao" />

<!-- 配置通知 -->
<bean id="myAroundAdvice" class="com.test.aop.demo4.MyAroundAdvice" />

<!-- 一般的切面是使用通知作为切面的,因为要对目标类的某个方法进行增强就需要配置一个带有切入点的切面 -->
<bean id="myAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    <!-- pattern 中配置正则表达式:. 任意字符 * 任意次数-->
    <!--<property name="pattern" value=".*save.*" />-->
    <property name="patterns" value=".*save.*,.*delete.*" />
    <property name="advice" ref="myAroundAdvice" />
</bean>

<!-- 配置产生代理 -->
<bean id="customerDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target" ref="customerDao" />
    <!-- 代表使用 CGLib 方法 -->
    <property name="proxyTargetClass" value="true" />
    <property name="interceptorNames" value="myAdvisor" />
</bean>

通知类:

public class MyAroundAdvice implements MethodInterceptor{


    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("环绕前增强...");

        // 执行目标方法
        Object obj = methodInvocation.proceed();

        System.out.println("环绕后增强...");

        return obj;
    }
}

具体代码:SpringDemo4.demo1()


6. 自动创建代理

前面的案例中,每个代理都是通过 ProxyFactoryBean 织入切面代理,在实际开发中,非常多的 Bean 每个都配置 ProxyFactoryBean 开发维护量巨大。

解决方案:自动创建代理。

自动创建代理的三种方式:


7. BeanNameAutoProxyCreator 举例

对所有以 Dao 结尾 Bean 所有方法使用代理:

<!-- 配置目标类 -->
<bean id="studentDao" class="com.test.aop.demo5.StudentDaoImpl" />
<bean id="customerDao" class="com.test.aop.demo5.CustomerDao" />

<!-- 配置增强 -->
<bean id="myAroundAdvice" class="com.test.aop.demo5.MyAroundAdvice" />
<bean id="myBeforeAdvice" class="com.test.aop.demo5.MyBeforeAdvice" />

<!-- 自动创建代理不需要 id -->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <property name="beanNames" value="*Dao" />
    <property name="interceptorNames" value="myBeforeAdvice" />
</bean>

具体代码:SpringDemo5.demo1()


8. DefaultAdvisorAutoProxyCreator 举例

配置环绕代理案例:

<!-- 配置目标类 -->
<bean id="studentDao" class="com.test.aop.demo6.StudentDaoImpl" />
<bean id="customerDao" class="com.test.aop.demo6.CustomerDao" />

<!-- 配置增强 -->
<bean id="myAroundAdvice" class="com.test.aop.demo6.MyAroundAdvice" />
<bean id="myBeforeAdvice" class="com.test.aop.demo6.MyBeforeAdvice" />

<!-- 配置切面 -->
<bean id="myAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    <property name="pattern" value="com\.test\.aop\.demo6\.CustomerDao\.save" />
    <property name="advice" ref="myAroundAdvice" />
</bean>

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />

具体代码:SpringDemo6.demo1()

上一篇 下一篇

猜你喜欢

热点阅读