Spring——AOP

一、概念

AOP(Aspect Oriented Programming),即面向切面编程。像日志,事务,安全等这些代码分散在各个业务逻辑之中,这样既会产生大量重复的代码也将这些逻辑与业务耦合起来。

AOP就是运用动态代理将

二、实现原理(JDK动态代理和Cglib动态代理)

JDK动态代理:代理对象实现目标对象的接口(目标对象一定是要有接口的,没有接口就不能实现动态代理)

Cglib动态代理:  代理对象继承目标对象。 

JDK动态代理

1、目标类接口:

public interface IUser {

    void save();
}

2、目标类

public class UserDao {

   public void save() {
       System.out.println("DB:保存用户");
    }
   
    public void delete() {
       System.out.println("DB:删除用户");
    }
}

3、测试类

public class AOP {

    public void begin() {
        System.out.println("开始事务");
    }
    public void close() {
        System.out.println("关闭事务");
    }
}

JDK动态代理

public class ProxyFactory {
    //维护目标对象
    private static Object target;

    //维护关键点代码的类
    private static AOP aop;
    public static Object getProxyInstance(Object target_, AOP aop_) {

        //目标对象和关键点代码的类都是通过外界传递进来
        target = target_;
        aop = aop_;

        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                        aop.begin();
                        Object returnValue = method.invoke(target, args);
                        aop.close();

                        return returnValue;
                    }
                }
        );
    }
}

Cglib动态代理:

/需要实现MethodInterceptor接口
public class ProxyFactory implements MethodInterceptor{

    // 维护目标对象
    private Object target;
    public ProxyFactory(Object target){
        this.target = target;
    }

    // 给目标对象创建代理对象
    public Object getProxyInstance(){
        //1. 工具类
        Enhancer en = new Enhancer();
        //2. 设置父类
        en.setSuperclass(target.getClass());
        //3. 设置回调函数
        en.setCallback(this);
        //4. 创建子类(代理对象)
        return en.create();
    }


    @Override
    public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {

        System.out.println("开始事务.....");

        // 执行目标对象的方法
        Object returnValue = method.invoke(target, args);

        System.out.println("提交事务.....");

        return returnValue;
    }

}

测试:

    public static void main(String[] args) {

        UserDao userDao = new UserDao();

        UserDao factory = (UserDao) new ProxyFactory(userDao).getProxyInstance();

        factory.save();
    }

三、AOP术语

连接点(Join point):目标对象里有哪些方法可以被增强,这些方法就是连接点。比如UserDao中的save()方法和delete()方法。

切点(Poincut):目标对象中具体被增强的方法。在上面的例子中就是UserDao的save()方法。

增强/通知(Advice):增强的方法。比如AOP的begin()方法和close()方法。

Spring AOP提供了5种Advice类型给我们:前置(被增强的方法之前)、后置(被增强的方法之后)、环绕(被增强的方法的前和后)、返回(后置之后)、异常。

切面(Aspect):由切点和增强/通知组成

四、AOP实现方式

1、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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">


    <!--对象实例-->
    <bean id="userDao" class="aa.UserDao"/>
    <bean id="orderDao" class="aa.OrderDao"/>

    <!--切面类-->
    <bean id="aop" class="aa.AOP"/>

    <!--AOP配置-->
    <aop:config >

        <!--定义切入表达式,拦截哪些方法-->
        <aop:pointcut id="pointCut" expression="execution(* aa.*.*(..))"/>

        <!--指定切面类是哪个-->
        <aop:aspect ref="aop">

            <!--指定来拦截的时候执行切面类的哪些方法-->
            <aop:before method="begin" pointcut-ref="pointCut"/>
            <aop:after method="close" pointcut-ref="pointCut"/>

        </aop:aspect>
    </aop:config>


</beans>

2、注解配置

在配置文件中开启注解配置方式

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


    <context:component-scan base-package="aa"/>

    <!-- 开启aop注解方式 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

常用注解:

  • @Aspect                            指定一个类为切面类

  • @Pointcut("execution(* cn.itcast.e_aop_anno..(..))")  指定切入点表达式

  • @Before("pointCut_()")                前置通知: 目标方法之前执行

  • @After("pointCut_()")                后置通知:目标方法之后执行(始终执行)

  • @AfterReturning("pointCut_()")            返回后通知: 执行方法结束前执行(异常不执行)

  • @AfterThrowing("pointCut_()")            异常通知:  出现异常时候执行

  • @Around("pointCut_()")                环绕通知: 环绕目标方法执行

@Component
@Aspect//指定为切面类
public class AOP {


    //里面的值为切入点表达式
    @Before("execution(* aa.*.*(..))")
    public void begin() {
        System.out.println("开始事务");
    }


    @After("execution(* aa.*.*(..))")
    public void close() {
        System.out.println("关闭事务");
    }
}

每次写Before、After等,都要重写一次切入点表达式,这样就不优雅了。于是我们可以用@Pointcut这个注解,来指定切入点表达式:

@Component
@Aspect//指定为切面类
public class AOP {


    // 指定切入点表达式,拦截哪个类的哪些方法
    @Pointcut("execution(* aa.*.*(..))")
    public void pt() {

    }

    @Before("pt()")
    public void begin() {
        System.out.println("开始事务");
    }


    @After("pt()")
    public void close() {
        System.out.println("关闭事务");
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值