1 aop是什么

  java的核心思想是面向对象,aop是面向切面编程.是对面向对象的一个补充,简单通俗的理解下aop,假设我们上楼梯,我的目标是三楼,我直接朝我的三楼直接过去,但是我可以在二楼的时候去朋友那里玩下,坐下其他的,然后再去三楼

这也不会影响我们的目标去三楼,那么去朋友那里玩,相当于增加的生活的乐趣去那里玩.相当于增强了我们的活动.

  那么aop可以做啥呢,可以进行日志记录,可以进行事务管理,可以进行安全控制,可以进行异常处理,可以进行性能统计

2 理解几个关键字

切面

关注点形成的类,就叫切面(类)!

面向切面编程,就是指对很多功能都有的重复的代码抽取,再在运行的时候网业务方法上动态植入“切面类代码”

切点

执行目标对象方法,动态植入切面代码。

可以通过切入点表达式,指定拦截哪些类的哪些方法; 给指定的类在运行的时候植入切面类代码。

通知

在对象上面执行的内容

3 aop的实现原理:

aop的底层实现是代理模式加反射.

反射就不用多讲了,代理模式分为多种,静态代理和动态代理,动态代理面又分为jdk动态代理和cglib动态代理

代理模式的好处:可以防止对方得到我们真实的方法;

静态代理的实现方式:

package com.cxy.cyclicBarrier;

/**
* Created by Administrator on 2017/4/24.
*/
public interface IUserDao {
void save();
}
package com.cxy.cyclicBarrier;

/**
* Created by Administrator on 2019/4/24.
*/
public class UserDao implements IUserDao {
@Override
public void save() {
System.out.println("已经保存数据");
}
}

代理类:

package com.cxy.cyclicBarrier;

/**
* Created by Administrator on 2019/4/24.
*/ public class UserDaoProxy implements IUserDao{
private IUserDao target; public UserDaoProxy(IUserDao iuserDao) {
this.target = iuserDao;
} public void save() {
System.out.println("开启事物...");
target.save();
System.out.println("关闭事物...");
} public static void main(String[] args) {
UserDao userDao=new UserDao();
UserDaoProxy userDaoProxy=new UserDaoProxy(userDao );
userDaoProxy.save();
} }

在最后可以看到执行结果:

结果分析:

静态代理:

由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。

然后再看jdk动态代理:

package com.cxy.cyclicBarrier;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; // 每次生成动态代理类对象时,实现了InvocationHandler接口的调用处理器对象
public class InvocationHandlerImpl implements InvocationHandler {
private Object target;// 这其实业务实现类对象,用来调用具体的业务方法
// 通过构造函数传入目标对象
public InvocationHandlerImpl(Object target) {
this.target = target;
} public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
System.out.println("调用开始处理");
result = method.invoke(target, args);
System.out.println("调用结束处理");
return result;
} public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// 被代理对象
IUserDao userDao = new UserDao();
InvocationHandlerImpl invocationHandlerImpl = new InvocationHandlerImpl(userDao);
ClassLoader loader = userDao.getClass().getClassLoader();
Class<?>[] interfaces = userDao.getClass().getInterfaces();
// 主要装载器、一组接口及调用处理动态代理实例
IUserDao newProxyInstance = (IUserDao) Proxy.newProxyInstance(loader, interfaces, invocationHandlerImpl);
newProxyInstance.save();
} }

结果分析:

jdk动态代理:

1. 通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(…);

2. 通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…});

3. 通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});

4. 通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));

cglib代理:

package com.cxy.cyclicBarrier;

import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {
private Object targetObject;
// 这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现了动态代理
public Object getInstance(Object target) {
// 设置需要创建子类的类
this.targetObject = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
} public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("开启事物");
Object result = proxy.invoke(targetObject, args);
System.out.println("关闭事物");
// 返回代理对象
return result;
} public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
UserDao userDao = (UserDao) cglibProxy.getInstance(new UserDao());
userDao.save();
}
}

执行结果:

在执行上面代码前需要引入asm包

原理:利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

4 区别比较:
CGLIB动态代理与JDK动态区别

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

Spring中。

1)、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP

2)、如果目标对象实现了接口,可以强制使用CGLIB实现AOP

3)、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

JDK动态代理只能对实现了接口的类生成代理,而不能针对类 。
CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 。
因为是继承,所以该类或方法最好不要声明成final ,final可以阻止继承和多态。

5 aop的使用方式:

1) 注解方式:

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>  开启事物注解权限
@Aspect 指定一个类为切面类
@Pointcut("execution(* com.xhz.service.UserService.add(..))") 指定切入点表达式
@Before("pointCut_()") 前置通知: 目标方法之前执行
@After("pointCut_()") 后置通知:目标方法之后执行(始终执行)
@AfterReturning("pointCut_()") 返回后通知: 执行方法结束前执行(异常不执行)
@AfterThrowing("pointCut_()") 异常通知: 出现异常时候执行
@Around("pointCut_()") 环绕通知: 环绕目标方法执行 @Component
@Aspect
public class AopLog { // 前置通知
@Before("execution(* com.cxy.service.UserService.add(..))")
public void begin() {
System.out.println("前置通知");
} //
// 后置通知
@After("execution(* com.cxy.service.UserService.add(..))")
public void commit() {
System.out.println("后置通知");
} // 运行通知
@AfterReturning("execution(* com.cxy.service.UserService.add(..))")
public void returning() {
System.out.println("运行通知");
} // 异常通知
@AfterThrowing("execution(* com.cxy.service.UserService.add(..))")
public void afterThrowing() {
System.out.println("异常通知");
} // 环绕通知
@Around("execution(* com.cxy.service.UserService.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕通知开始");
proceedingJoinPoint.proceed();
System.out.println("环绕通知结束");
}
}

2)xml方式:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- dao 实例 --> <bean id="userService" class="com.cxy.service.UserService"></bean>
<!-- 切面类 -->
<bean id="aop" class="com.cxy.aop2.AopLog2"></bean>
<!-- Aop配置 -->
<aop:config>
<!-- 定义一个切入点表达式: 拦截哪些方法 -->
<aop:pointcut expression="execution(* com.cxy.service.UserService.*(..))"
id="pt" />
<!-- 切面 -->
<aop:aspect ref="aop">
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pt" />
<!-- 前置通知: 在目标方法调用前执行 -->
<aop:before method="begin" pointcut-ref="pt" />
<!-- 后置通知: -->
<aop:after method="after" pointcut-ref="pt" />
<!-- 返回后通知 -->
<aop:after-returning method="afterReturning"
pointcut-ref="pt" />
<!-- 异常通知 -->
<aop:after-throwing method="afterThrowing"
pointcut-ref="pt" />
</aop:aspect>
</aop:config> </beans>
public class AopLog2 {

    // 前置通知
public void begin() {
System.out.println("前置通知");
} //
// 后置通知
public void commit() {
System.out.println("后置通知");
} // 运行通知
public void returning() {
System.out.println("运行通知");
} // 异常通知
public void afterThrowing() {
System.out.println("异常通知");
} // 环绕通知
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕通知开始");
proceedingJoinPoint.proceed();
System.out.println("环绕通知结束");
}
}

再也不怕aop的原理了的更多相关文章

  1. 【Spring】Spring AOP实现原理

    Spring AOP实现原理 在之前的一文中介绍过Spring AOP的功能使用,但是没有深究AOP的实现原理,今天正好看到几篇好文,于是就自己整理了一下AOP实现的几种方式,同时把代理模式相关知识也 ...

  2. Spring AOP 实现原理

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...

  3. Spring核心框架 - AOP的原理及源码解析

    一.AOP的体系结构 如下图所示:(引自AOP联盟) 层次3语言和开发环境:基础是指待增加对象或者目标对象:切面通常包括对于基础的增加应用:配置是指AOP体系中提供的配置环境或者编织配置,通过该配置A ...

  4. 何为代理?jdk动态代理与cglib代理、spring Aop代理原理浅析

    原创声明:本博客来源为本人原创作品,绝非他处摘取,转摘请联系博主 代理(proxy)的定义:为某对象提供代理服务,拥有操作代理对象的功能,在某些情况下,当客户不想或者不能直接引用另一个对象,而代理对象 ...

  5. 循序渐进之Spring AOP(1) - 原理

    AOP全称是Aspect Oriented Programing,通常译为面向切面编程.利用AOP可以对面向对象编程做很好的补充. 用生活中的改装车比喻,工厂用面向对象的方法制造好汽车后,车主往往有些 ...

  6. Spring Aop底层原理详解

    Spring Aop底层原理详解(来源于csdn:https://blog.csdn.net/baomw)

  7. 深入浅析Spring的AOP实现原理

    转载来源:https://www.jb51.net/article/81788.htm AOP(Aspect-OrientedProgramming,面向切面编程),可以说是OOP(Object-Or ...

  8. spring AOP底层原理实现——jdk动态代理

    spring AOP底层原理实现——jdk动态代理

  9. Spring AOP底层原理

    ------------------siwuxie095                                 Spring AOP 底层原理         AOP 即 Aspect Or ...

随机推荐

  1. cmake 强制链接静态库

    add_executable(main main.cpp) target_link_libraries(main ${CMAKE_SOURCE_DIR}/libbingitup.a) 静态库和动态库共 ...

  2. C#中DateTime的各种操作

    C#时间戳与日期互转 /// <summary> /// 时间戳转为C#格式时间 /// </summary> /// <param name="timeSta ...

  3. Linux confluence5.8.10 wiki安装

    选择首先需要java环境 其次需要mysql mysql安装请参考: http://www.cnblogs.com/syuf/p/7818710.html 安装好mysql之后,创建一个库 # mys ...

  4. 利率计算v5.0--结对--软件工程

    利率计算v5.--测试--软件工程 1.任务结对同伴: 名字:王昕明 学号: 博客地址 :http://home.cnblogs.com/u/xinmingwang/ Git : https://gi ...

  5. python virtualenv环境安装(ubuntu)

    测试系统ubantu16.04 该系统已经默认安装了python3.5, 当然了python2.7也同时存在着. 可以用如下命令安装pip(如下命令会默认安装pip到python2.7库中) $ su ...

  6. VS2010+SVN

    小乌龟版本用1.6,用1.8时老报错SVN是2.06, SVN Server是2.1.9

  7. Oracle学习笔记(九)

    十二.PL/SQL 1.PL/SQL程序的结构和组成 示例:给员工涨工资(根据职位涨工资) 总裁涨1000 经理涨800 其他员工涨400 学习原因:1.操作数据库效率最高 2.为了后期的存储过程的学 ...

  8. 通过HttpClient请求webService

    通过HttpClient请求webService 由于服务端是用webService开发的,android要调用webService服务获取数据,这里采用的是通过HttpClient发送post请求, ...

  9. EBS11i - 常用Profile

      Profile Name 说明 设置建议 FND: Enable Cancel Query 当执行一个超长时间的查询时,会出现一个 Cancel窗口,允许用户取消.比如我们在SO 界面没有输入条件 ...

  10. 咏南 DATASNAP LINUX中间件

    咏南 DATASNAP LINUX中间件,一套源码,同时支持WINDOWS和LINUX操作系统. 基于DELPHI 10.2 TOKYO开发 使用FIREDAC数据库引擎,支持MYSQL,MSSQL, ...