AOP(三)

什么是AOP

       AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP(面向对象编程)的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低提高程序的可重用性,同时提高了开发的效率。AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码。经典应用:事务管理、性能监视、安全检查、缓存 、日志等

Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码。

AspectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入。

AOP的实现原理:

  Aop底层将采用代理机制进行实现。

 接口+实现类:spring采用jdk的动态代理

 实现类:spring采用cglib代理

AOP的术语:

1. target: 目标对象,需要被代理的类

2. joinpoint:连接点,指那些可能被拦截到的方法

3. pointCut:切入点,已经被增强的连接点

4. advice:通知/增强,增强的代码

5. weaving:织入,是指把增强advice应用到目标对象target来创建新的代理对象Proxy的过程

6. Proxy:代理类

7. Aspect:切面,是切入点pointcut和advice的结合,

一个线是一个特殊的面。一个切入点和一个通知组成一个特殊的面。

手动实现JDK代理

必须实现接口

目标类:

public interface EmployeeService {
	public void addEmployee();
	public void updateEmployee();
	public void deleteEmployee();
}
package com.dsx.spring_proxy;
//目标类
public class EmployeeServiceImp implements EmployeeService {

	@Override
	public void addEmployee() {
		System.out.println("执行了添加用户的方法");
	}

	@Override
	public void updateEmployee() {
		System.out.println("执行了updateEmployee的方法");
	}

	@Override
	public void deleteEmployee() {
		System.out.println("执行了deleteEmployee的方法");
	}

}

切面类:

package com.dsx.spring_proxy;
//切面类
public class MyAspect {
	public void before() {
		System.out.println("开启事务");
	}
	public void after() {
		System.out.println("关闭事务");
	}
}

工厂类:

package com.dsx.spring_proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


public class MyBeanFactory {
	public static EmployeeService createEmployeeService() {
		//1.目标类
		final EmployeeService employeeService= new EmployeeServiceImp();
		System.out.println("目标类:"+employeeService);
		//2.切面类
		final MyAspect aspect = new MyAspect();
		//3.代理类--将目标类与切面类的结合
		/**
		 * newProxyInstance(arg0, arg1, arg2)
		 * 参数一:类加载器,一般写当前类
		 * 参数2:代理类所需要实现的接口
		 * 参数3:处理类,一般写匿名类
		 */
		EmployeeService proxyInstance =(EmployeeService) Proxy.newProxyInstance(
				MyBeanFactory.class.getClassLoader(), 
				employeeService.getClass().getInterfaces(),
				new InvocationHandler() {
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						//执行前
						aspect.before();
						//放行
						Object obj = method.invoke(employeeService,args);
						//执行后
						aspect.after();
						return obj;
					}
				});
		
		return proxyInstance;
	}	
	
}

测试类:

手动实现cglib代理

1. 没有接口,只有实现类

2. 采用字节码增强框架cglib,在运行时创建目标类的子类,从而对目标对象进行增强。

3.导入jar包  spring-core.jar

目标类

package com.dsx.spring_cglib;

public class EmployeeServiceImp {
	public void addEmployee() {
		System.out.println("执行了添加用户的方法");
	}

	public void updateEmployee() {
		System.out.println("执行了updateEmployee的方法");
	}

	public void deleteEmployee() {
		System.out.println("执行了deleteEmployee的方法");
	}
}

切面类

package com.dsx.spring_cglib;
//切面类
public class MyAspect {
	public void before() {
		System.out.println("开启事务");
	}
	public void after() {
		System.out.println("关闭事务");
	}
}

工厂类

package com.dsx.spring_cglib;


import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;


public class MyBeanFactory {
	public static EmployeeServiceImp createEmployeeService() {
		//1.目标类
		final EmployeeServiceImp employeeService= new EmployeeServiceImp();
		System.out.println("目标类:"+employeeService);
		//2.切面类
		final MyAspect aspect = new MyAspect();
		//3.cglib代理  核心类
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(employeeService.getClass());
		enhancer.setCallback(new MethodInterceptor() {
			@Override
			public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
				aspect.before();
				//执行目标类的方法
			//	method.invoke(employeeService, args);
				//执行代理类的方法(目标类和代理类是父子关系)
				Object obj = methodProxy.invokeSuper(proxy, args);
				aspect.after();
				return obj;
			}
			
		});
		EmployeeServiceImp proxy = (EmployeeServiceImp)enhancer.create();
		return proxy;
	}	
	
}

测试类

Aop联盟通知类型

AOP联盟为通知Advice定义了org.aopalliance.aop.Advice。spring按照通知advice在目标类方法的连接点位置,可以分为5类:

1. 前置通知

org.springframework.aop.MethodBeforeAdvice 在目标方法执行前实施增强

2. 后置通知

org.springframework.aop.AfterReturningAdvice 在目标方法之后实施增强

3. 环绕通知

org.aopalliance.intercept.MethodInterceptor  在目标方法执行前后实施增强

4. 异常抛出通知

org.springframework.aop.ThrowsAdvice 在方法抛出异常后实施增强

5. 引介通知 

org.springframework.aop.IntroductionInterceptor 在目标类中添加一些新的方法和属性

注意:

     环绕通知,必须手动执行目标方法

try{

      //前置通知

      // 执行目标方法

     //后置通知

}catch(){

   //抛出异常通知

}

spring编写代理半自动

让spring创建代理对象,从spring容器中手动的获取代理对象

1. 导包

2. 目标类

package com.dsx.spring_proxy2;

public interface EmployeeService {
	public void addEmployee();
	public void updateEmployee();
	public void deleteEmployee();
}

 

package com.dsx.spring_proxy2;
//目标类
public class EmployeeServiceImp implements EmployeeService {

	@Override
	public void addEmployee() {
		System.out.println("执行了添加用户的方法");
	}

	@Override
	public void updateEmployee() {
		System.out.println("执行了updateEmployee的方法");
	}

	@Override
	public void deleteEmployee() {
		System.out.println("执行了deleteEmployee的方法");
	}

}

切面类

我们使用的是环绕通知,是aop联盟的,注意不要导错jar包。

package com.dsx.spring_proxy2;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

//切面类
public class MyAspect implements MethodInterceptor {
	
	@Override
	public Object invoke(MethodInvocation inv) throws Throwable {
		System.out.println("前。。。。。");
		Object obj = inv.proceed();
		System.out.println("后。。。。。");
		return obj;
	}
}

配置文件

<!-- 业务类 -->
  <bean id="employeeServiceImp" class="com.dsx.spring_proxy2.EmployeeServiceImp" />
  <!-- 切面类 -->
  <bean id="myAspect" class="com.dsx.spring_proxy2.MyAspect"/>
  <!-- 
  	使用工厂bean来创建代理
  	interface:确定接口,多个接口使用Array,单个使用value
  	target:确定目标
  	interceptorNames:通知,切面类,它是一个数组
  	注意:默认使用jdk代理
  	如果目标类有接口使用jdk代理
  	没有接口,采用cglib字节码增强
  	如果声明optimize = true,无论是否有接口,都采用cglib
   -->
  <bean id="proxyService" class="org.springframework.aop.framework.ProxyFactoryBean">
  	<property name="interfaces" value="com.dsx.spring_proxy2.EmployeeService"/>
  	<property name="target" ref="employeeServiceImp"/>
  	<property name="interceptorNames" value="myAspect"/>
    <!--使用cglib创建代理  -->
    <!-- <property name="optimize" value="true"/> -->
  </bean>

测试类

    @Test
	public void test1() {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
		EmployeeService bean = (EmployeeService) context.getBean("proxyService");
		bean.addEmployee();
	}

Spring AOP全自动编程

从spring容器中获得目标类,如果配置了aop。spring将自动生成代理。

要确定目标类,aspectJ:切点表达式,导包

spring的AOP配置

测试:

    @Test
	public void test1() {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/com/dsx/spring_aop/bean.xml");
		//此处直接获取目标类
		EmployeeService bean = (EmployeeService) context.getBean("employeeServiceImp");
		bean.addEmployee();
	}

以上便是spring 的AOP的一个demo演示过程。 

对spring的aop是否有一个具体的认识呢?在项目实战当中,aop占据了很重要的位置,小伙伴们务必要好好掌握哟!对spring的AOP的理解可以参考博客:https://blog.csdn.net/duan196_118/article/details/104133176。下篇博客介绍AspectJ.

如有不足,欢迎留言指正。望不吝赐教。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值