AOP:面向切面编程.(思想.---解决OOP遇到一些问题)
????????AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视、事务管理、安全检查、缓存)
为什么要学习AOP,可以在不修改源代码的前提下,对程序进行增强!!
说到增强你觉得AOP和谁比较像? 没错是代理 ,不了解看这篇文章00=》【javaSE】代理并不难-CSDN博客
JDK的动态代理技术
? 1、为接口创建代理类的字节码文件
? 2、使用ClassLoader将字节码文件加载到JVM
? 3、创建代理类实例对象,执行对象的目标方法
cglib代理技术
1、创建拦截器:继承MethodInterceptor的 intercepter的类,在拦截器中重写intercerpt( )方法,就是增强+目标对象的方法调用,返回拦截器
2、在测试这边创建一个类似proxy的子类对象enhancer,然后设置这个代理对象的类型(setSuperclass(目标对象的类型.class完成))
3、创建一个拦截器,enhancer通过去设置回调函数(setCallback(拦截器))
4、创建代理对象enhancer.create(),代理对象的类型要和目标对象一致哈,然后通过代理对象去完成方法的调用
Spring的AOP代理默认用的就是JDK代理方式来实现的,在Spring中,ProxyFactoryBean是创建AOP代理的最基本方法(不常用,后面有更好的方法)
ProxyFactoryBean是FactoryBean接口的实现类,FactoryBean负责实例化一个Bean,而ProxyFactoryBean负责为其他Bean创建代理实例。
target | 代理的目标对象 |
proxyInterfaces | 代理要实现的接口,如果有多个接口,可以使用一些形式赋值 ... |
proxyTargetClass | 是否对类代理而不是接口,设置为true时,使用CGLIB代理 |
interceptorNames | 需要织入目标的Advice |
singleton | 返回的代理是否为单实例,默认为true |
optimize | 设置为true,强制使用CGLIB |
导包
在核心jar包基础上导入AOP的jar包,
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
编写配置类?
package com.aqiuo.factorybean;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
//切面类。实现了MethodInterceptor方法拦截器接口
public class MyAscpect implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
check_permissions();
Object object= mi.proceed();
log();
return object;
}
//增强的方法体--通知
public void check_permissions() {
System.out.println("模拟权限检查");
}
//增强的方法体--通知
public void log() {
System.out.println("模拟日志记录");
}
}
?编写配置文件
//application.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd " >
<!-- 目标类 用的是jdk的对象 -->
<bean id="accountService" class="com.aqiuo.service.impl.AccountServiceImpl"></bean>
<!-- 切面类 -->
<bean id="myAspect" class="com.aqiuo.aspect.MyAspect02"></bean>
<!-- 使用Spring工厂定义一个名称为userDaoProxy的代理对象 -->
<bean id="userDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 指定代理要实现的接口 -->
<property name="proxyInterfaces" value="com.aqiuo.service.AccountService"></property>
<!-- 指定目标对象 -->
<property name="target" ref="accountService"></property>
<!-- 指定切面,执行环绕通知 -->
<property name="interceptorNames" value="myAspect"></property>
<!-- 指定代理方式 -->
<property name="proxyTargetClass" value="true"></property>
</bean>
</beans>
//测试
强调:获取的对象是代理之后的对象,不是原来的目标对象,获取原来的目标对象是不会有增强的?
@Test
public void run2() throws SQLException {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService accountService= (AccountService) applicationContext.getBean("userDaoProxy");
accountService.pay(100,1,2);
}
在上述代码中,首先通过bean元素定义了目标类和切面,然后使用ProxyFactoryBean类定义了代理对象。
????????在定义的代理对象中,分别通过子元素指定了代理实现的接口、代理的对象、需要织入的目标类的通知,已经代理方式
?下篇文章讲解AOP的AspectJ,AspectJ是一个居于JAVA开发的AOP框架》》框架