Spring实现AOP(使用API接口、使用自定义类、使用注解)

AOP

image-20200823135537461

不改变原有的业务,增加功能

AOP在Spring中的作用

  • 横切关注点:跨越应用程序多个模块的方法或功能,于我们业务逻辑无关,但需要关注的部分
  • 切面(aspect):横切关注点被模块化的特殊对象,是一个类
  • 通知(Adivce):切面必须要完成的工作,类中的一个方法
  • 目标(Target):被通知的对象
  • 代理(Proxy):向目标对象应用通知后创建的对象
  • 切入点(PointCut):切面通知 执行的“地点”的定义
  • 连接点(JointPoint):于切入点匹配的执行点

image-20200823140201540

SpringAOP中,通过Advice定义横切逻辑,支持五种类型的的advice

image-20200823140425900

AOP不改变原有代码的情况下,去增加新的功能

使用Spring实现AOP

使用Spring的API接口

  • 导入包

    • <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.9.5</version>
      </dependency>
      
  • 添加applicationContext.xml配置支持

    • xmlns:aop="http://www.springframework.org/schema/aop"
      http://www.springframework.org/schema/aop
      https://www.springframework.org/schema/aop/spring-aop.xsd
      
  • 找到对应的接口和实现类,实现类就是被代理对象

    • public interface UserService {
          public void add();
          public void delete();
          public void update();
          public void select();
      }
      
    • public class UserServiceImpl implements UserService{
      
          public void add() {
              System.out.println("add");
          }
      
          public void delete() {
              System.out.println("delete");
          }
      
          public void update() {
              System.out.println("update");
          }
      
          public void select() {
              System.out.println("select");
      
          }
      }
      
    • 现在制作一个动态代理的横切关注点,需要加在原有的业务前,原有业务执行前,执行这个切片

  • 制作切片

    • public class Log implements MethodBeforeAdvice {
          ///**
          // * @param method:要执行目标对象的方法
          // * @param args:参数
          // * @param target:目标对象
          // * @throws Throwable
          // */
          public void before(Method method, Object[] args, Object target) throws Throwable {
              System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行");
      
          }
      }
      
    • before中是切片执行的方法,通知方式是before,前置通知

  • 把这个横切关注点加入beans,和

    • <bean id="log" class="com.haoyun.log.Log"/>
      <bean id="UserServiceImpl" class="com.haoyun.service.UserServiceImpl"/>
      
  • applicationContext.xml配置AOP切入点,切片环绕

    • <aop:config>
          <!--切入点:expression:表达式(要执行的位置,UserServiceImpl.要切入的方法)-->
          <aop:pointcut id="pointcut" expression="execution(* com.haoyun.service.UserServiceImpl.*(..))"/>
          <!--执行环绕增加-->
          <!--把log切片,切入到pointcut切入点上-->
          <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
      </aop:config>
      
  • 测试

    • @Test
      public void ProxyTest() {
          ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
          /*代理的是一个接口*/
          UserService userserviceImpl = (UserService) context.getBean("UserServiceImpl",UserService.class);
          userserviceImpl.add();
      }
      
    • image-20200823152603918

    • 执行add前会先执行log切面

使用自定义类

  • public class aspectDiy {
        public void beforeDiy(){
            System.out.println("beforeDiy");
        }
        public void afterDiy(){
            System.out.println("afterDiy");
        }
    }
    
  • <aop:config>
        <aop:aspect ref="aspectDip">
            <!--切入点-->
            <aop:pointcut id="pointcut" expression="execution(* com.haoyun.service.UserServiceImpl.*(..))"/>
            <!--通知,切入到哪个点上-->
            <aop:before method="beforeDiy" pointcut-ref="pointcut"/>
            <aop:after method="afterDiy" pointcut-ref="pointcut"/>
        </aop:aspect>
    
    </aop:config>
    
  • 选择对应的方法切入就行

  • beforeDiy
    add
    afterDiy
    

使用注解实现

  • 先开启注解支持

  •     <aop:aspectj-autoproxy/>
        <context:component-scan base-package="com.haoyun.pointCut"/>
    
  • @Aspect
    @Component
    public class AnnotationPointCut {
        @Before("execution(* com.haoyun.service.UserServiceImpl.*(..))")
        public void before(){
            System.out.println(AnnotationPointCut.class.getName()+"   before");
        }
        @After("execution(* com.haoyun.service.UserServiceImpl.*(..))")
        public void after(){
            System.out.println(AnnotationPointCut.class.getName()+"   after");
        }
    
    }
    
  • 和之前一样测试就行

规范点的化使用第一种方法吧,切面小的话使用第二种方法,第三种方法也不是很简便,要设置切入点还挺麻烦,第一和第二种方法的切入点都可以复用,第三种方法切入点不好复用,差点意思

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
非常抱歉,我之前给出的代码有误。确实,通过自定义注解AOP实现指定接口在没有Token的情况下可以访问的功能是不正确的。在Spring Security中,AOP是无法绕过安全过滤器链进行授权和认证的。 要实现指定接口在没有Token的情况下可以访问,可以考虑以下方法: 1. 创建一个自定义过滤器`NoTokenFilter`,用于拦截指定的接口,并跳过Spring Security的Token验证。 ```java @Component public class NoTokenFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 获取请求路径 String requestPath = request.getRequestURI(); // 判断是否为需要跳过Token验证的接口 if (isNoTokenRequired(requestPath)) { filterChain.doFilter(request, response); return; } // 非跳过Token验证的接口,执行Spring Security的Token验证逻辑 // ... } private boolean isNoTokenRequired(String requestPath) { // 判断请求路径是否为需要跳过Token验证的接口 // 返回true表示需要跳过Token验证,返回false表示不需要跳过Token验证 // ... } } ``` 2. 配置Spring Security,将自定义过滤器添加到Spring Security的过滤器链中。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private NoTokenFilter noTokenFilter; @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() // 配置需要Token验证的接口 .anyRequest().authenticated() .and() .csrf().disable(); // 将自定义过滤器添加到Spring Security的过滤器链中 http.addFilterBefore(noTokenFilter, UsernamePasswordAuthenticationFilter.class); } @Bean public NoTokenFilter noTokenFilter() { return new NoTokenFilter(); } } ``` 3. 在需要不需要Token验证的接口上,使用`@NoTokenRequired`注解标记。 ```java @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface NoTokenRequired { } ``` ```java @RestController public class ExampleController { @NoTokenRequired @GetMapping("/example") public String example() { return "This API does not require Token"; } } ``` 通过以上配置,带有`@NoTokenRequired`注解接口将会跳过Spring Security的Token验证,即可在没有Token的情况下访问该接口。其他接口仍然需要进行Token验证。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值