zoukankan      html  css  js  c++  java
  • Spring AOP

     ProxyFactoryBean类

    FactoryBean接口用于Bean的实例化,ProxyFactoryBean是它的一个实现类,用于实例化代理(Bean)。

    spring  aop是用动态代理实现的,自己写jdk动态代理、cglib代理很麻烦,spring用ProxyFactoryBean封装了jdk动态代理、cglib动态代理,我们只需在xml中配置代理即可,不必手写动态代理。


    Demo

    (1)添加spring-aop.RELEASE.jar

    Spring  AOP需要spring-aop.RELEASE.jar的支持。(待修改)

    (2)目标接口、目标类

    新建包com.chy.dao,包下新建接口UserDao、实现类UserDaoImpl:

    public interface UserDao {
        public void addUser();
        public void deleteUser();
    }
    public class UserDaoImpl implements UserDao {
        @Override
        public void addUser() {
            System.out.println("正在添加用户...");
        }
    
        @Override
        public void deleteUser() {
            System.out.println("正在删除用户...");
        }
    }

    (3)切面

    新建包com.chy.aspect,包下新建类UserDaoAspect:

    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    
    public class UserDaoAspect implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation methodInvocation) throws Throwable {
            //前增强
            System.out.println("正在执行前增强...");
            //调用目标方法,返回值是Object类型
            Object object=methodInvocation.proceed();
            //后增强
            System.out.println("正在执行后增强...");
            //返回目标方法的返回值
            return object;
        }
    }

    注意实现的接口是spring-aop.RELEASE.jar中的aopalliance包下的接口:

    import org.aopalliance.intercept.MethodInterceptor;

    是spring aop封装好的接口,不必手写代理。

    不是spring内嵌的cglib包下的接口:

    import org.springframework.cglib.proxy.MethodInterceptor

    spring内嵌了cglib需要的jar,这个MethodInterceptor是cglib的原生接口,需要手写动态代理。


    实现相应的接口即可:

      通知类型
    对应的接口
    环绕通知     MethodInterceptor    
    前置通知 MethodBeforeAdvice
    后置通知

    AfterAdvice(空接口)

    异常通知 ThrowsAdvice(空接口)
    返回通知 AfterReturningAdvice  

     一般不使用空接口。

    虽然AfterReturningAdvice是返回通知,但很多时候都可以作为后置通知使用。

    示例     前增强

    import org.springframework.aop.MethodBeforeAdvice;
    import java.lang.reflect.Method;
    
    public class UserDaoAspect implements MethodBeforeAdvice {
        @Override
        public void before(Method method, Object[] objects, Object o) throws Throwable {
            System.out.println("前增强...");
        }
    }

      

    (4)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" 
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
        
        <!-- 目标类-->
        <bean name="userDaoImpl" class="com.chy.dao.UserDaoImpl" />
    
        <!-- 切面-->
        <bean name="userDaoAspect" class="com.chy.aspect.UserDaoAspect" />
    
        <!-- 配置ProxyFactoryBean类,用于生产代理对象-->
        <bean name="userDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <!--指定要代理的接口,如果实现了多个接口,用子元素<list>来写-->
            <property name="proxyInterfaces" value="com.chy.dao.UserDao" />
            <!--指定目标对象-->
            <property name="target" ref="userDaoImpl" />
            <!--指定切面,只能用value,不能用ref-->
            <property name="interceptorNames" value="userDaoAspect" />
            <!-- 是否直接代理目标类
            true:直接代理目标类,目标类不必实现接口,使用的是cglib动态代理
            false:默认值,代理接口,目标类必须实现接口,使用的是jdk动态代理
            -->
            <property name="proxyTargetClass" value="false" />
            <!--返回的代理对象是否使用单例,默认为true 单例-->
            <property name="singleton" value="true" />
        </bean>
    </beans>

    ProxyFactoryBean类封装好了创建代理的代码,我们只需使用<property>注入参数即可。

    上面的配置代理的是目标接口,如果只代理目标类:

    • 不配置proxyInterfaces(不注入目标接口)
    • 将proxyTargetClass的值改为true(代理目标类)


      

    (5)使用

    ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-config.xml");
    UserDao user=applicationContext.getBean("userDaoProxy", UserDao.class);
    user.addUser();

     会自动增强方法。

  • 相关阅读:
    Laravel 底层原理:门面(Facades)
    用 PHP和Golang 来刷leetCode 之 无重复字符 最长子串
    今天发现一个好用的查询IP地址的工具,记录一波
    Ubuntu下安装SDL
    敏捷宣言
    python 读取xml文档
    每个程序员都必须遵守的编程原则
    作为Web开发人员,我为什么喜欢Google Chrome浏览器
    爬虫
    Python为什么要self
  • 原文地址:https://www.cnblogs.com/chy18883701161/p/11139169.html
Copyright © 2011-2022 走看看