Java Web——Spring Aop

 

面向切面的编程——AOP

AOP在Spring中的作用:1.提供声明式事务     2.允许用户实现自定义切面    3.不改变原有的代码,增加新的功能(其本质通过代理)

注解:不用写动态代理,简化开发。将公共业务(日志、安全、权限、缓存、事务)等与领域业务相结合,使领域业务更加纯粹。

专业词(部分,有时间再补充):

切面:Aspect         连接点:JoinPoint       通知:Advice      织入:Weaving

实现AOP的三种方式

1.使用Spring  API实现AOP

  • 建立Spring_Aop1工程
  • 建立cn.jx.log包,创建Log.java(日志)
  •  
package cn.jx.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[]args, Object target)
        throws Throwable{
        System.out.println(target.getClass().getName() + "的" + method.getName() + "方法被执行");
    }
}
  • 业务层示例
  • 建cn.jx.service包,包下的UserService.java接口
  •  
package cn.jx.service;

public interface UserService {
    public void add();
    public void update();
    public void delete();
    public void search();
}
  • 建cn.jx.serviceImpl包,包下的UserServiceImpl.java接口
  •  
package cn.jx.serviceImpl;

import cn.jx.service.UserService;

public class UserServiceImpl implements UserService {
    @Override
    public void add(){
        System.out.println("增加用户");
    }
    public void update(){
        System.out.println("修改用户");
    }
    public void delete(){
        System.out.println("删除用户");
    }
    public void search(){
        System.out.println("查询用户");
    }
}
  • beans.xml配置
  • 导入AOP相关头文件 ,去官方文档找即可
  • 建立userServiceImpl和Log之间的关系
  • bean标签之前的全是头文件,没啥可看的,其实就下边6行代码
  •  
<?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:context="http://www.springframework.org/schema/context"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd
		http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd"
       default-lazy-init="true">


    <bean id = "userService" class="cn.jx.serviceImpl.UserServiceImpl"/>
    <bean id = "Log" class="cn.jx.log.Log"/>

    <!--为上面两个id建立关系,由Spring提供动态代理-->
    <aop:config>
        <aop:pointcut id="pointuct" expression="execution(* cn.jx.serviceImpl.UserServiceImpl.add())"/>
        <aop:advisor advice-ref="Log" pointcut-ref="pointuct"/>
    </aop:config>
</beans>
  • 写Test方法,测试类
  •  
import cn.jx.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AopTest {
    @Test
    public void aopTest(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        UserService userService = (UserService) ac.getBean("userService");
        userService.add();
    }

}

实现结果截图

工程截图
第一种实现方式

2.使用自定义类实现AOP

  • 业务层service和serviceImpl都不变,Test也不变
  • Log日志增加后置通知和before与after两个自定义方法
  • 改beans.xml配置文件
  • 修改后
    execution(* cn.jx.serviceImpl.*.*(..))可以调用业务层里所有方法
  • 改后的Log.java
package cn.jx.log;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice {
    @Override
    //前置通知
    public void before(Method method, Object[]args, Object target)
        throws Throwable{
        System.out.println(target.getClass().getName() + "的" + method.getName() + "方法被执行");
    }
    public void before(){
        System.out.println("方法执行前");
    }

    //后置通知
    public class AfterLog implements AfterReturningAdvice{
        /**
         *
         * 目标方法执行后的通知
         * @param method        被调用方法对象
         * @param returnvalue  返回值
         * @param target       目标对象
         * @throws Throwable
         */
        @Override
        public void afterReturning(Object returnvalue, Method method,
                                   Object[] args, Object target) throws Throwable {

            System.out.println(target.getClass().getName() + "的" + method.getName() + "方法被执行,返回值:" +returnvalue);
        }
    }
    public void after(){
        System.out.println("方法执行后");
    }
}
  • 改后的beans.xml配置文件——头文件省略了啊
  <bean id = "userService" class="cn.jx.serviceImpl.UserServiceImpl"/>
    <bean id = "Log" class="cn.jx.log.Log"/>

    <aop:config>
        <aop:aspect ref="Log">
            <!--cn.jx.serviceImpl包下所有类的所有方法的所有参数-->
            <aop:pointcut id="pointcut" expression="execution(* cn.jx.serviceImpl.*.*(..))"/>
            <!--前置通知-->
            <aop:before method="before" pointcut-ref="pointcut"/>
            <!--后置通知-->
            <aop:after method="after" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

实现结果截图

第二种实现方式

3.使用注解实现AOP(简单易用)

  • beans.xml文件增加一句代码即可
    <aop:aspectj-autoproxy/>

在Log.java中进行注解,代码如下

package cn.jx.log;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

import java.lang.reflect.Method;
@Aspect         //注解表示它是一个切面
public class Log  {
    @Before("execution(* cn.jx.service.*.*(..))")
    public void before(){
        System.out.println("方法执行前");
    }
    @After("execution(* cn.jx.service.*.*(..))")
    public void after(){
        System.out.println("方法执行后");
    }
}

beans.xml

    <bean id = "userService" class="cn.jx.serviceImpl.UserServiceImpl"/>
    <bean id = "Log" class="cn.jx.log.Log"/>
    <aop:aspectj-autoproxy/>

实现结果截图

第三种方式

猜你喜欢

转载自blog.csdn.net/qq_38663663/article/details/82956329