关于AOP

一、动态代理

1. 作用:利用插件一样的东西去解决新的需求,切入到原代码,但可以不改变原有的代码和逻辑。

2. 需求:比如需要添加有一个方法的统计时间/输出日志等,如果在方法中添加过于冗余。

3. 缺点:不能对单独的一个方法进行控制。

4. 如何使用:

  1. 真实对象必须是实现某个接口的对应
  2. 申明代理对象(接口),在InvocationHandler接口实现,在匿名内部类中去调用真实对象的方法。
  3. 对代理对象进行实例化,利用Proxy.newProxyInstance,实际是使用了反射机制。
 final UserDao userDao = new UserDao();
    // 代理对象(快捷方式)
    IUserDao iUserDao = null;
    //2. 对真实对象的调用逻辑要在InvocationHandler接口里做
    InvocationHandler invocationHandler = new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("UserDao " + method.getName() + " run ..");
            long start= System.currentTimeMillis();

            Object invoke = method.invoke(userDao, args);

            long end = System.currentTimeMillis();
            System.out.println("UserDao " +method.getName() + " end ..,耗时:" + (end - start) + "毫秒");
            //当我们有需要把这些执行数据存到数据库时,我们只需要在这里增加相关的数据库操作代码即可,其它任何地方都不需要做修改。
            return invoke;
        }
    };

    // 代理对象实例化:
    iUserDao = (IUserDao) Proxy.newProxyInstance(
            UserDao.class.getClassLoader(),
            new Class[]{IUserDao.class},invocationHandler);
            //.getClassLoader() ---->对应的是真实对象
            //Class<?>[] ----->真实对象的接口

    return iUserDao;
}

二、AOP 面向切面编程

  1. 定义:OOP的延续,是动态代理的一种实现方式。在运行期间,不修改原代码的情况下对方法进行增强。

  2. 优势:可以对业务逻辑的各个部分进行隔离,是的业务逻辑的耦合度降低,减少重复代码,提高重用性,提高开发效率

  3. 理解:AOP实际是对动态代理进行了封装,通过配置的方法来对方法进行增强。

  4. 重要概念:

  • target目标对象: 真实对象
  • proxy代理:代理对象(接口)
  • joinpoint:拦截点-----> 方法
  • poincut切入点:对哪些 Joinpoint 进行拦截 ,相当于查询条件
  • advice通知:拦截到joinpoint之后的增强
  • aspect切面:把当前类定义为一个切面供容器读取 = poincut + advice
  • weaing织入:把advice应用到target的过程,spring采用动态织入

5. 步骤:

a 导入依赖

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.13</version>
</dependency>

b 创建target和接口proxy

public class Target implements ITarget{
    @Override
    public void method() {
        System.out.println("run......");
    }
}

c 创建aspect切面

public class MyAspect {
    public void before(){
        System.out.println("before");
    }
}

d xml配置

<bean id="target" class="day02.Target"/>
//id为唯一标识,通过反射拿到目标对象
<bean id="aspect" class="day02.MyAspect"/>
//拿到切面

d 导入aop命名空间

xmlns:aop="Index of /schema/aop"

Index of /schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd

e 配置织入关系

<aop:config>
    <aop:aspect ref="aspect">
    //调用id为aspect对应的方法
        <aop:before method="before" pointcut="execution(public void day02.Target.method())"></aop:before>
    //在拦截点前执行方法名为before的方法
    //execution就是切入条件(我要在那些点上做增强) 
    </aop:aspect>
</aop:config>

----------------------------------------------------------------------------------------------------------------------------

**execution([修饰符] 返回值类型 包名.类名.方法名(参数))

----------------------------------------------------------------------------------------------------------------------------

***关于环绕:

通常配合ProceedingJoinPoint

public void around(ProceedingJoinPoint proceedingJoinPoint) {
    System.out.println("around welcome 调用的方法名:" + proceedingJoinPoint.getSignature().getName());
    System.out.println("around 调用类:" + proceedingJoinPoint.getSignature().getDeclaringTypeName());
    System.out.println("around 调用类名:" + proceedingJoinPoint.getSignature().getDeclaringType().getSimpleName());
    try {
        proceedingJoinPoint.proceed();
    } catch (Throwable e) {
        e.printStackTrace();
    }
    System.out.println("环绕");
}

//输出为:
//around welcome 调用的方法名:method
//around 调用类:day02.ITarget
//around 调用类名:ITarget
//run......
//环绕

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值