Spring-03

8 篇文章 0 订阅

1 aop编程的一些概念
2 使用 Spring 创建代理对象(注解方式)
3 关于切入点相关的参数的说明
4 环绕通知
 

一、AOP编程的一些概念

为什么要用AOP:可以看这篇文章(26条消息) 为什么需要使用Spring AOP(代理模式)_清思越的博客-CSDN博客

Aspect切面:横切性关注点的抽象

Joinpoint连接点:指的是拦截到的点,在spring中,指的就是被拦到的方法,比如addUser()等

pointCut 切入点:指的是对那些连接点进行拦截,比如,对所有的以get开头的方法进行计时

Advice 通知:拦到 Joinpoint 以后,要做的动作就叫通知,有前置通知、后置通知、最终通知、例外通知、环绕通知

Target 被代理的目标对象

Weave 织入:将Aspect 应用到目标对象的过程,经过织入以后,代理对象就产生了

二、使用 spring 创建代理对象(注解方式)

spring中进行AOP 编程,有两种方式:

        注解方式

        XML配置方式

1)注解方式:

  (1) 要导入相应的jar,加入配置构建路径
              aspectjweaver-1.8.9.jar 
              cglib-3.2.2.jar
         
                   如果用maven,则依赖如下
                         

  <dependency>
         <groupId>org.aspectj</groupId>
         <artifactId>aspectjweaver</artifactId>
         <version>1.8.9</version>
  </dependency>
  <dependency>
       <groupId>cglib</groupId>
       <artifactId>cglib</artifactId>
       <version>3.2.2</version>
   </dependency>

(2)创建spring的主配置文件,打开AOP的名称空间

<?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: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-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
	<context:component-scan base-package="com.dao"/>
	<context:component-scan base-package="com.servlet"/>
	
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

(3)切面类

package com.aop;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect //必须要加入切面注解
@Component  //交给spring管理
public class Myaspect {
	/*excution表示要拦截的正在执行的方法
	  excution(int)里面的int表示要拦截的方法的返回值
	  excution(*)表示不管什么样的返回值都拦截
	*/
/*
 *  excution(“返回值 拦截的方法”)
    excution("*  com.dao.UserDao.*(int,String)")下面对应
    excution("返回值   拦截那个类下的那个方法.*(*表示所有方法)(int,String代表这个方法的返回值是什么,不在意返回值的话就(..))
 */

	@Pointcut("execution(* com.dao.UserDaoImpl.*(..))") //切入点,想要对那些方法进行拦截
	private void anyMethod() {}
	
	//我要拦的不是pointCut里面的这些方法吗,那么在拦截这些方法之前我要执行我下面这个事
	@Before("anyMethod()")
	public void  beforeMethod() {
		System.out.println("前置通知触发了");
	}
	
	//后置通知:和前置通知相对应
	@AfterReturning("anyMethod()")
	public void afterMethod() {
		System.out.println("后置通知触发了");
	}
	//最终通知
	@After("anyMethod()")
	public void finallyMethod() {
		System.out.println("最终通知触发了");
	}
	
	//例外通知
	@AfterThrowing("anyMethod()")
	public void execptionMethod() {
		System.out.println("出现异常,例外通知触发了");
	}
	
	
	
}


                    execution() //表示拦截正在执行的方法
                    * //表示不管方法的返回值是什么都拦
                    com.dao.UserDaoImpl //表示拦截哪个包下的哪个类
                    * 表示不管这个方法的名字是什么
                    (..) //表示不管方法的参数是什么 

 3 关于切入点相关的参数的说明

  //例 通过 JoinPoint 叁数,得到方法的名称和得到目标对象
         

   @Before("anyMethodAAA()") 
            public void beforMethod(JoinPoint point) {
                //得到被拦截的方法的名称
                String methodName=point.getSignature().getName();
                if("delUser".equals(methodName)) {
                    System.out.println("将调用删除方法,日志已记录...");
                }
                
                //得到目标对象 
                UserDaoImpl imp=(UserDaoImpl)point.getTarget();
                System.out.println("目标对象的userName属性值是:"+imp.getUserName());
                
                //得到方法的参数
                Object  [] params =point.getArgs(); 
                for(Object param:params) {
                    System.out.println(param);
                }
                
                    
                System.out.println("前置通知触发了");
            }
        
         //例子 进一步限定切入点的条件 ,只拦截带两个参数的                  
            @Before("anyMethodAAA()&&args(a,b)")  //前置通知
            public void beforMethod(String a,String b) {
                System.out.println("得到的参数是"+ a  +" 和 "+ b);
                System.out.println("前置通知触发了");
            }
            
            这个通知,将只能作用于带两个 String 参数的方法
            
            


         //例子 取得方法执行的返回值
         

   @AfterReturning(pointcut = "anyMethodAAA()",returning = "result")  //后置通知
            public void afterMethod(int result) {
                System.out.println("方法的返回值是 "+result);
                System.out.println("后置通知触发了");
            }
            
            经过上面的处理以后,只有接口中有int型返回值的方法才能触发上面的后置通知,比如下面这个方法
                            public int getUserCount() {
                                         System.out.println("getUserCount 执行了");
                                         return 9/3;
                                    }
                        

            
        
//例子 取得异常信息
             

@AfterThrowing(pointcut="anyMethodAAA()",throwing = "ex")
            public void exceptionMethod(Exception ex) {
                System.out.println("出错,异常信息是"+ex.getMessage());
                System.out.println("出现异常,例外通知触发了");
            }
  

4、环绕通知


		@Pointcut("execution(* com.dao.UserDaoImpl.*(..))")
		private void anyMethodAAA() {}
		
		@Around("anyMethodAAA()")
		public Object aroundMethod(ProceedingJoinPoint point) {
			Object result=null;
	
			String methodName=point.getSignature().getName();
			System.out.println("当前拦到的方法是:"+methodName);
			
			try {
				System.out.println("环绕通知 前置通知触发了");
				//让目标方法执行
				result=point.proceed();
				
				System.out.println("环绕通知 后置通知触发了");
				
			}catch(Throwable ex) {
				ex.printStackTrace();
				System.out.println("环绕通知 例通知触发了");
			}finally {
				System.out.println("环绕通知 最终知触发了");
			}
					
			return result;
			
		}

实际项目中,我们哪些地方需要做切面呢?

1)数据访问层

2)控制层

3)业务层

一般来说AOP主要用于日志记录、权限控制

             

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用spring-integration-webflux的DSL实现客户端和服务端流式交互需要以下步骤: 1. 引入依赖 在pom.xml文件中引入以下依赖: ```xml <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-webflux</artifactId> </dependency> ``` 2. 创建服务端 使用WebFlux.fn来创建服务端,示例代码如下: ```java import org.springframework.http.MediaType; import org.springframework.integration.dsl.IntegrationFlow; import org.springframework.integration.dsl.MessageChannels; import org.springframework.integration.webflux.dsl.WebFlux; import org.springframework.stereotype.Component; @Component public class Server { public IntegrationFlow serverFlow() { return IntegrationFlows.from(WebFlux.inboundGateway("/stream") .requestMapping(m -> m.produces(MediaType.APPLICATION_STREAM_JSON_VALUE)) .requestPayloadType(String.class)) .channel(MessageChannels.flux()) .log() .map(String::toUpperCase) .map(s -> s + "-stream") .get(); } } ``` 该方法创建了一个接收客户端请求的WebFlux.inboundGateway,并将请求传递给MessageChannels.flux()通道,接着执行一些转换操作,并返回结果。在示例中,将请求转换为大写并添加后缀“-stream”。 3. 创建客户端 使用WebFlux.fn来创建客户端,示例代码如下: ```java import org.springframework.http.MediaType; import org.springframework.integration.dsl.IntegrationFlow; import org.springframework.integration.dsl.MessageChannels; import org.springframework.integration.webflux.dsl.WebFlux; import org.springframework.stereotype.Component; @Component public class Client { public IntegrationFlow clientFlow() { return IntegrationFlows.from(MessageChannels.flux()) .handle(WebFlux.outboundGateway("http://localhost:8080/stream") .httpMethod(HttpMethod.POST) .expectedResponseType(String.class) .expectedResponseType(MediaType.APPLICATION_STREAM_JSON_VALUE)) .log() .get(); } } ``` 该方法从MessageChannels.flux()通道接收请求,并将请求发送到WebFlux.outboundGateway,该网关将请求发送到服务端的“/stream”端点。示例中,期望响应为String类型,MediaType为APPLICATION_STREAM_JSON_VALUE。 4. 创建Spring应用程序 在Spring Boot应用程序的主类中,创建Spring Integration流: ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.integration.dsl.IntegrationFlow; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean public IntegrationFlow serverFlow(Server server) { return server.serverFlow(); } @Bean public IntegrationFlow clientFlow(Client client) { return client.clientFlow(); } } ``` 5. 测试 启动应用程序并访问http://localhost:8080/stream,应该能看到类似以下的输出: ``` 2019-12-03 16:37:45.947 INFO 6282 --- [ctor-http-nio-2] o.s.integration.handler.LoggingHandler : GenericMessage [payload=Hello, world!, headers={id=0c9be9f7-191f-8b1a-3f92-12d2c2bd8eaa, contentType=application/json;charset=UTF-8}] 2019-12-03 16:37:45.947 INFO 6282 --- [ctor-http-nio-2] o.s.integration.handler.LoggingHandler : GenericMessage [payload=HELLO, WORLD!-STREAM, headers={id=dcf0d3c6-9bca-2c39-0f7c-5d5b5db5c5a8, contentType=application/json;charset=UTF-8}] ``` 这表示客户端已成功将请求发送到服务端,并且服务端已成功执行转换操作并将响应发送回客户端。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值