day3 springAOP

day3 springAOP

AOP,面向切面开发。在不修改源代码的基础上增加新的功能。

AOP 底层原理

​ 底层使用动态代理

  1. 有 接口(使用 jdk 的动态代理)

    创建有接口的实现类的代理对象,使用代理对象增强功能方法 。

    接口,调用newProxyInstance方法

    class Proxy{
        static object newProxyInstance(ClassLoader loader,<?>[] interfaces,InvocationHandler h)
    }
    参数1:类加载器
    
    参数2:增强方法所在类实现的接口,支持多个接口
    
    参数3:需要实现的接口,创建对象,增强部分
    

    代码

    interface UserDao {
        public int add(int a,int b);
        public String update(String id);
    }
    class UserDaoImpl implements UserDao{
        @Override
        public int add(int a, int b) {
            return a+b;
        }
    
        @Override
        public String update(String id) {
            return id;
        }
    }
    
    class UserDaoProxy implements InvocationHandler{
    
        private Object obj;
        public UserDaoProxy(Object obj){
            this.obj = obj;
        }
        // 增强的逻辑
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 方法之前
            System.out.println("方法前执行..."+method.getName()+"; 参数:"+ Arrays.toString(args));
    
            // 方法执行
            // invoke 参数1:实现类对象,    参数2:传入参数
            Object res = method.invoke(obj, args);
    
            // 方法之后执行
            System.out.println("方法执行后...");
    
            return res;
        }
    }
    
    class JDKProxy {
        public static void main(String[] args) {
            // 创建接口实现类的代理对象
            Class[] interfaces = {UserDao.class};
    
            UserDaoImpl userDao = new UserDaoImpl();
            UserDao user = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
            int res = user.add(12, 5);
            System.out.println(res);
        }
    }
    
  2. 没有接口(使用 cglib 的动态代理)

    创建当前类的子类代理对象,增强类的方法

AOP术语

1.连接点

2.切入点

3.通知(增强)

class User{
    add(){}
    update(){}
}
  1. 连接点

    类中哪些方法可以被增强,这些方法为连接点

  2. 切入点

    实际被增强的方法,称为切入点

  3. 通知(增强)

    (1) 实际增强的逻辑部分称为通知(增强)

    (2) 通知分为多种类型

    • 前置通知 方法前执行
      • 后置通知 方法后执行
      • 环绕通知 方法前后都执行
      • 异常通知 方法出现异常执行
      • 最终通知 最终执行,finally
  4. 切面

    动作,指把通知应用到切入点的过程

AOP 操作

  1. Spring 框架一般都是基于 AspectJ 实现 AOP 操作

    AspectJ 是一个独立的 aop 框架,一般把 AspectJ 和 spring 框架一起使用,进行 AOP 操作

  2. 基于 AspectJ 实现 aop

    1. 基于 xml 配置文件实现
    2. 基于注解的方式实现
  3. 在项目工程中引入相关依赖 jar

  4. 切入点表达式

    1. 作用:知道对哪个类里的哪个方法进行增强

    2. 语法结构

      execution( [权限修饰符] [返回类型] [类的全路径] [方法名] [参数列表])

    例子

    execution( * com.edu.test.add(..))
    
基于 AspectJ 注解,实现AOP操作
  1. 创建类,在类中定义方法

    @Component	// 生成对象
    public class User {
        public void add(){
            System.out.println("方法执行");
        }
    }
    
  2. 创建增强类,编写增强逻辑

    在增强类里,创建方法,让不同方法代表不同通知类型

    @Component	// 生成对象
    @Aspect		// 设置增强类
    public class UserProxy {
        public void before(){
            System.out.println("before...");
        }
    }
    
  3. 进行通知的配置

    (1) 在 spring 配置文件中,开启注解扫描

    (2) 使用注解创建 User 和 UserProxy 对象

    (3) 在增强类上添加注解 @Aspect

    (4) 在 spring 配置文件中开启生成代理对象的配置

    spring 配置文件
    
    添加命名空间 context、aop
    
    <!-- 开启注解扫描 -->
    <context:component-scan base-package="com.edu"></context:component-scan>
    
    <!-- 开启 Aspect 生成代理对象 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    <!-- 找到声明 Aspect 的类声明为注解对象 -->
    
  4. 配置不同类型的通知

    在增强类的里边,在作为通知的方法上边,添加通知类型的注解,并使用切入点表达式来配置内容。

    @Before( value=" execution( * com.edu.user.add(…)) " )

  5. 测试

    @Test
    public void test(){
        ApplicationContext context 
            = new ClassPathXmlApplicationContext("bean.xml");
    	User user = context.getBean("user",User.class);
        user.add();
    }
    

其他注解

  • @After(value="") 结束后执行,最终通知,即使有报错也会通知
  • @AfterReturning(value="") 结束并返回后执行
  • @AfterThrowing(value="") 异常通知
  • @Around(value="") 环绕通知

顺序

环绕之前
before
方法
环绕之后
after
afterReturning
  1. 关于 相同的切入点抽取
@Pointcut(value="execution( * com.edu.user.add(...))")
public void pointDemo(){
    
}

@Before(value="pointDemo()")
public void before(){
    
}
@After(value="pointDemo()")
public void after(){
    
}
  1. 有多个增强类对同一个方法进行增强,设置增强类优先级

    在增强类上添加一个注解 @Order(value) ,value值越小,优先级越高

    @Component
    @Aspect
    @Order(1)
    public class UserProxy{}
    
基于 AspectJ 配置文件,实现AOP操作
1. 创建两个类,增强类和被增强类,创建方法
2. 在 spring 配置文件中创建两个类对象
3. 在 spring 配置文件中配置切入点
完全注解开发

使用注解,完全替代xml配置

@Configuration
@ComponentScan(basePackages = {"com.edu"})			//扫描
@EnableAspectJAutoProxy(proxyTargetClass = true)	//开启AspectJ生成代理对象
public class ConfigAop{

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值