JAVA AOP

AOP背景

 

Dijkstra--separation of concerns(分散关注)

所谓的分离关注就是将某一通用的需求功能从不相关的类之中分离出来;同时,能够使得很多类共享一个行为,一旦行为发生变化,不必修改很多类,只要修改这个行为就可以。

设计模式孜孜不倦追求的是调用者和被调用者之间的解耦。

OOP-面向对象编程

针对问题领域中以及业务处理过程中存在的实体及其属性和操作进行抽象和封装。

面向对象的核心概念是纵向结构的,其目的是获得更加清晰高效的逻辑单元划分。

 

 

AOP:Aspect oriented programming. AOP实际是设计模式的一种扩展,提供从另一个角度来考虑程序结构以完善面向对象编程(OOP)。

面向对象将应用程序分解成各个层次的对象。

而AOP将程序分解成各个方面或者说关注点这使得可以模块化诸如事务管理等这些横切多个对象的关注点。(这些关注点术语称作横切关注点。)

AOP的核心思想就是将应用程序中的业务逻辑处理部分同对其提供支持的通用服务,即所谓的“横切关注点”进行分离,这些“横切关注点”贯穿了程序中的多个纵向模块的需求。

事务

安全

日志……

 

 

 

AOP是一个概念,并没有设定具体语言的实现,它能克服那些只有单继承特性语言的缺点(如Java),目前AOP具体实现有以下几个项目:

AspectJ (TM):创建于Xerox PARC. 有近十年历史,成熟。缺点:过于复杂;破坏封装;需要专门的Java编译器。

动态AOP:使用JDK的动态代理API或字节码Bytecode处理技术。

 

 

AOP目的


 



 

应用切面


 

 

基于JAVA动态代理的AOP实现原理

 

 

public class AOPHandler implements InvocationHandler {
	private List interceptors = null;
	private Object objOriginal;
	
	public Object bind(Object objOriginal) {
		this.objOriginal = objOriginal;
                //返回动态代理实例
		return Proxy.newProxyInstance(objOriginal.getClass().getClassLoader(), objOriginal.getClass().getInterfaces(), this);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object result = null;
		Throwable ex = null;
		InvocationInfo invInfo = new InvocationInfo(proxy, method, args, objOriginal, ex);
                //预执行
		invokeInterceptorsBefore(invInfo);	
		try {
			result = method.invoke(objOriginal, args);
			invInfo.setResult(result);
                        //后执行
			invokeInterceptorsAfter(invInfo);
		} catch (Exception e) {
			invInfo.setException(e);
                        //异常执行
			invokeInterceptorsException(invInfo);
		}
		return result;
	}
	//加载Interceptor
	private synchronized List getInterceptors() {
		if(interceptors == null) {
			interceptors = new ArrayList();
			Properties p = new Properties();
			ClassLoader loader = AOPHandler.class.getClassLoader();
			try {
				p.load(loader.getResourceAsStream("interceptor.properties"));
				String interceptorName = p.getProperty("interceptorName");
				Class cl = Class.forName(interceptorName);
				interceptors.add(cl.getConstructor(new Class[]{}).newInstance(new Object[]{}));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return interceptors;
	}

	private void invokeInterceptorsBefore(InvocationInfo invInfo) {
		interceptors = getInterceptors();
		int len = interceptors.size();
		for(int i=0; i<len; i++) {
			((MyInterceptor) interceptors.get(i)).before(invInfo);
		}
	}
	
	private void invokeInterceptorsAfter(InvocationInfo invInfo) {
		interceptors = getInterceptors();
		int len = interceptors.size();
		for(int i=0; i<len; i++) {
			((MyInterceptor) interceptors.get(i)).after(invInfo);
		}
	}
	
	private void invokeInterceptorsException(InvocationInfo invInfo) {
		interceptors = getInterceptors();
		int len = interceptors.size();
		for(int i=0; i<len; i++) {
			((MyInterceptor) interceptors.get(i)).exceptionThrow(invInfo);
		}
	}
}

 

 

 

interceptor.properties配置文件:

InterceptorName=com.ht.MyInterceptor

 

 

拦截信息基本类

 

public class InvocationInfo {
	private Object proxy;
	private Method method;
	private Object[] args;
	private Object result;
	private Throwable exception;
	
	public InvocationInfo(Object proxy, Method method, Object[] args, Object result, Throwable exception) {
		this.proxy = proxy;
		this.method = method;
		this.args = args;
		this.result = result;
		this.exception = exception;
	}
	
	public Object getProxy() {
		return proxy;
	}
	public void setProxy(Object proxy) {
		this.proxy = proxy;
	}
	public Method getMethod() {
		return method;
	}
	public void setMethod(Method method) {
		this.method = method;
	}
	public Object[] getArgs() {
		return args;
	}
	public void setArgs(Object[] args) {
		this.args = args;
	}
	public Object getResult() {
		return result;
	}
	public void setResult(Object result) {
		this.result = result;
	}
	public Throwable getException() {
		return exception;
	}
	public void setException(Throwable exception) {
		this.exception = exception;
	}
}

 

 

自定义拦截器接口

public interface Interceptor {
	public void before(InvocationInfo invInfo);
	public void after(InvocationInfo invInfo);
	public void exceptionThrow(InvocationInfo invInfo);
}

 

具体拦截器实现

public class MyInterceptor implements Interceptor {

	@Override
	public void before(InvocationInfo invInfo) {
		System.out.println("pre processing...");
	}

	@Override
	public void after(InvocationInfo invInfo) {
		System.out.println("post processing...");
	}

	@Override
	public void exceptionThrow(InvocationInfo invInfo) {
		System.out.println("exception processing...");
	}
}

 

AOP 工厂类建立

public class AOPFactory {
	public static Object getProxyInstance(String clName) {
		AOPHandler handler = new AOPHandler();
		Class c;
		Object proxy = null;
		try {
			c = Class.forName(clName);
			proxy = handler.bind(c.newInstance());
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return proxy;
	}
}

执行

HelloWorld proxy = (HelloWorld) AOPFactory.getProxyInstance("com.ht.HelloWorldImpl");
proxy.sayHello();

 

注:实例proxy与HelloWorldImpl 均实现了统一的HelloWorld接口定义方法,通过建立代理可以方便地将日志,安全等事务进行委托。

 

10-11
Java AOP般称为面向切面,作为面向对象OOP的种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块之间的耦合度,提高了系统的可维护性,可用于权限认证,日志和事务处理[^4]。 使用Java AOP的方法步骤如下: 1. **依赖引入**:在项目中添加AOP相关依赖,确保项目能够使用AOP的功能。 2. **标注类为切面类**:使用特定注解将类标注为切面类,表明该类是AOP切面。 3. **定义切入点函数列表**:确定哪些方法会被AOP拦截和增强,通过特定的表达式来定义。 4. **定义签名函数**:定义在切入点函数执行前后等不同时机要执行的具体方法。 5. **增强方法**:实现具体的增强逻辑,如前置通知、环绕通知、后置通知、返回通知、报错通知等。 6. **aop全局注解**:可以使用全局注解来简化配置和使用。 以下是Java AOP的案例: ### 案例:基于Spring Boot的简单实践 1. **依赖引入**:添加相关依赖。 2. **项目包结构**:搭建好项目的包结构。 3. **项目启动类**:启动项目的主类。 4. **切面类**: - **类创建**:创建切面类。 - **切点实现**:定义切入点。 - **前置通知**:在目标方法执行前执行的通知。 - **环绕通知**:可以在目标方法执行前后进行操作。 - **后置通知**:在目标方法执行后执行的通知。 - **返回通知**:在目标方法正常返回后执行的通知。 - **报错通知**:在目标方法抛出异常时执行的通知。 - **完整切面类代码**:整合上述各种通知的完整代码。 5. **请求接口的实现**:创建多个请求接口类,如AopTestController.javaAopTest2Controller.javaAopTest3Controller.java。 6. **测试接口**:对不同请求接口的方法进行测试。 7. **输出打印**:查看不同测试方法的输出结果。 ### 案例二:简单实例演示 1. **包结构**:搭建项目的包结构。 2. **依赖**:添加AOP相关依赖。 3. **项目启动类**:启动项目的主类。 4. **请求类**:创建请求类。 5. **切面类**:实现切面逻辑。 6. **执行AOP**: - **启动程序**:启动项目。 - **postman访问**:使用postman工具访问接口。 - **控制台输出**:查看控制台的输出结果。 ### 案例三:入门案例 ```java public class AspectAop1 { @Pointcut("execution(* com.********.************Impl.*(..))") public void pt(){ } @Before("pt()") public void before(){ System.out.println("之前aop1"); } @AfterReturning("pt()") public void afterReturing(){ System.out.println("执行之后,抛出异常不会执行aop1"); } @After("pt()") public void after(){ System.out.println("最后执行aop1"); } @AfterThrowing(value = "pt()",throwing = "e") public void afterTh(Throwable e){ e.printStackTrace(); System.out.println("异常通知增强aop1"); } } ``` ### 案例四:Spring Aop案例 ```java package org.example.aop; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Component @Aspect//当作Aop处理 public class MyAdvice { @Pointcut("execution(void org.example.dao.BookDao.update())") private void pt(){} @Before("pt()") public void method(){ System.out.println(System.currentTimeMillis()); } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值