一、AOP概述

  AOP(Aspect Oriented Programing),面向切面编程,AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视、事务管理、安全检查、缓存)
  Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码
  AspecJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入

二、AOP的术语:

  • 连接点(Joinpoint):所谓连接点是指那些被拦截到的点。在Spring中,这些点指的是方法,因为Spring只支持方法类型的连接点.
  • 切入点(Pointcut):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义.
  • 通知/增强(Advice):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.
    • 前置通知(Before advice):在目标方法被调用之前调用通知方法
    • 后置通知(After/finally advice):在目标方法完成之后 调用通知方法,此时不会关心方法的输出是什么
    • 返回通知(After returning advice):在目标方法成功执行之后调用通知
    • 异常通知(After throwing advice):在目标方法抛出异常之后调用通知
    • 环绕通知(Around advice):通知包裹了被通知的方法,在被通知的方法调用之前调用之后执行自定义的行为
  • 引介/引入(Introduction):引介是一种特殊的通知,在不修改类代码的前提下,Introduction可以在运行期为类动态地添加一些方法或Field
  • 目标对象(Target):代理的目标对象
  • 织入(Weaving):是指把增强应用到目标对象创建新的代理对象的过程. Spring采用动态代理织入,而AspectJ采用编译期织入和类装在期织入
  • 代理(Proxy):一个类被AOP织入增强后,就产生一个结果代理类
  • 切面(Aspect):是切入点和通知(引介)的结合

三、AOP底层原理

SpringAOP实现机制主要有两种:

  1. JDK动态代理:对实现了接口的类生成代理
  2. CGLib代理机制:对类生成代理

详见代理模式

四、Spring 中的AOP

1. 概述

2. 分类

  1. 基于代理的经典Spring AOP(传统AOP)
  2. 纯POJO切面;
  3. @AspectJ注解驱动的切面;
  4. 注入式AspectJ切面(适用于Spring各版本)。

3. Spring的传统AOP

  AOP:不是由Spring定义.AOP联盟的组织定义.

Spring中的通知:(增强代码)

  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

针对所有方法的增强:(不带有切点的切面)

需要引入的Maven坐标:

<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.1.5.RELEASE</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.1.5.RELEASE</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.5.RELEASE</version>
<!-- 这里要注释掉,因为设置了scope为test是,测试类只能卸载 Maven中的测试包下 -->
<!-- <scope>test</scope> -->
</dependency>

编写被代理对象

接口:

public interface ICustomerDao {
public void add();
public void update();
public void delete();
public void find();
}

实现类:

public class CustomerDaoImpl implements ICustomerDao {
@Override
public void add() {
System.out.println("添加客户");
}
@Override
public void update() {
System.out.println("更新客户");
}
@Override
public void delete() {
System.out.println("删除客户");
}
@Override
public void find() {
System.out.println("查询客户");
}
}

编写增强的代码

前置增强:

import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
// TODO Auto-generated method stub
System.out.println("前置增强。。。。。");
} }

生成代理:(在XML中配置生成代理)

<!-- 不带有切点的切面 -->
<!-- 1.定义目标对象 -->
<bean id="customerDao"
class="com.hao.aop.tradition.demo1.CustomerDaoImpl"></bean> <!-- 2.定义增强 -->
<bean id="beforeAdvice"
class="com.hao.aop.tradition.demo1.MyBeforeAdvice"></bean> <!-- 3.Spring支持配置生成代理: -->
<bean id="customerDaoProxy"
class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 设置目标对象 -->
<property name="target" ref="customerDao" /> <!-- 设置代理要实现的接口 -->
<property name="proxyInterfaces"
value="com.hao.aop.tradition.demo1.ICustomerDao"></property> <!-- 设置需要织入目标的Advice -->
<property name="interceptorNames" value="beforeAdvice" />
</bean>

在XML配置说明:

  • 首先要将前面定义的目标对象增强 注册到Spring 容器中,
  • 然后是代理类的配置(主要是这里的配置):
    通过类 org.springframework.aop.framework.ProxyFactoryBean 来设置代理对象,对于这个类,以后有时间要看一下,下面先看一下它在XML中需要配置的属性:

    • target : 代理的目标对象
    • proxyInterfaces : 代理要实现的接口,如果多个接口可以使用以下格式赋值:

      <list>
      <value></value>
      ....
      </list>
    • proxyTargetClass:是否对类代理而不是接口,设置为true时,使用CGLib代理

    • interceptorNames : 需要织入目标的Advice

    • singleton : 返回代理是否为单实例,默认为单例

    • optimize : 当设置为true时,强制使用CGLib

测试

这里要注意的是,要注入代理对象!!!!

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AOPTest1 { @Qualifier("customerDaoProxy")
@Autowired
private ICustomerDao customerDao; @Test
public void test() {
customerDao.add();
customerDao.find();
customerDao.update();
customerDao.delete();
}
}

带有切点的切面:(针对目标对象的某些方法进行增强)

创建目标对象:

这里没有实现接口,这里试下用CGLIB代理的方式

public class OrderDao {
public void add() {
System.out.println("添加订单");
}
public void delete() {
System.out.println("删除订单");
} public void find() {
System.out.println("查询订单");
}
}

编写增强的类:

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; public class MyAroundAdvice implements MethodInterceptor{ @Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("执行方法之前增强.....");
Object result = invocation.proceed();
System.out.println("指向方法之后增强.....");
return result;
} }

生成代理(配置生成代理):

<!-- 定义带有切点的切面 -->

    <!-- 定义目标对象 -->
<bean id="orderDao" class="com.hao.aop.tradition.demo2.OrderDao"></bean> <!-- 定义增强 -->
<bean id="aroundAdvice"
class="com.hao.aop.tradition.demo2.MyAroundAdvice"></bean> <!-- 定义切面 -->
<bean id="myPointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!-- 定义表达式,规定哪些方法执行拦截 -->
<!-- . 任意字符 * 任意个 -->
<property name="patterns" value=".*add.*,.*find.*"></property> <!-- 应用增强 -->
<property name="advice" ref="aroundAdvice"/>
</bean> <!-- 定义生成代理对象 -->
<bean id="orderDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 配置目标 -->
<property name="target" ref="orderDao"></property>
<!-- 针对类的代理 -->
<property name="proxyTargetClass" value="true"></property>
<!-- 在目标上应用增强 -->
<property name="interceptorNames" value="myPointcutAdvisor"></property>
</bean>

测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AOPTest2 { @Qualifier("orderDaoProxy") //此处注入的是代理对象
@Autowired
private OrderDao orderDao; @Test
public void test() {
orderDao.add();
orderDao.delete();
orderDao.find();
}
}

4. 自动代理

  前面的案例中,每个代理都是通过ProxyFactoryBean织入切面代理,在实际开发中,非常多的Bean每个都配置ProxyFactoryBean开发维护量巨大

  自动创建代理(基于后处理Bean,在Bean创建的过程中完成的增强,生成Bean就是代理。前面利用ProxyFactoryBean代理的方式需要先生成代理对象才可以实现代理功能,而这种方式在Bean的创建过程中就可以完成代码的增强)
  

  • BeanNameAutoProxyCreator:根据Bean名称创建代理
  • DefaultAdvisorAutoProxyCreator:根据Advisor本身包含信息创建代理
  • AnnotationAwareAspectJAutoProxyCreator:基于Bean中的AspectJ 注解进行自动代理

BeanNameAutoProxyCreator

  目标对象和增强,应用前面中的例子,配置示例:
  

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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.xsd"> <!-- 自动代理 -->
<!-- 目标对象 -->
<bean id="customerDao" class="com.hao.aop.tradition.demo1.CustomerDaoImpl"></bean>
<bean id="orderDao" class="com.hao.aop.tradition.demo2.OrderDao"></bean> <!-- 定义增强-->
<bean id="beforeAdvice" class="com.hao.aop.tradition.demo1.MyBeforeAdvice"></bean>
<bean id="aroundAdvice" class="com.hao.aop.tradition.demo2.MyAroundAdvice"></bean> <!-- 自动代理:按名称的代理 基于后处理Bean,后处理Bean不需要配置ID-->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="*Dao"/>
<property name="interceptorNames" value="aroundAdvice"/>
</bean>
</beans>

测试代码:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.hao.aop.tradition.demo1.ICustomerDao;
import com.hao.aop.tradition.demo2.OrderDao; @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class AOPTest3 { @Qualifier("customerDao")
@Autowired
private ICustomerDao customerDao; @Qualifier("orderDao")
@Autowired
private OrderDao orderDao; @Test
public void test() {
orderDao.add();
orderDao.find();
customerDao.add();
customerDao.delete();
}
}

DefaultAdvisorAutoProxyCreator

根据切面本身包含信息创建代理
配置示例:

<!-- 目标对象 -->
<bean id="customerDao" class="com.hao.aop.tradition.demo1.CustomerDaoImpl"></bean>
<bean id="orderDao" class="com.hao.aop.tradition.demo2.OrderDao"></bean> <!-- 定义增强-->
<bean id="beforeAdvice" class="com.hao.aop.tradition.demo1.MyBeforeAdvice"></bean>
<bean id="aroundAdvice" class="com.hao.aop.tradition.demo2.MyAroundAdvice"></bean> <!-- 定义一个带有切点的切面 -->
<bean id="myPointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="pattern" value=".*add.*"/>
<property name="advice" ref="aroundAdvice"/>
</bean> <!-- 自动生成代理 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>

测试代码:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.hao.aop.tradition.demo1.ICustomerDao;
import com.hao.aop.tradition.demo2.OrderDao; @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext3.xml")
public class AOPTest4 { @Autowired
@Qualifier("customerDao")
private ICustomerDao customerDao; @Autowired
@Qualifier("orderDao")
private OrderDao orderDao; @Test
public void test() {
customerDao.add();
customerDao.update(); orderDao.add();
orderDao.delete();
}
}

区别:基于ProxyFattoryBean的代理与自动代理

  • ProxyFactoryBean:先有被代理对象,将被代理对象传入到代理类中生成代理.
  • 自动代理基于后处理Bean.在Bean的生成过程中,就产生了代理对象,把代理对象返回.生成Bean已经是代理对象.

5. AspectJ

概述

AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
AspectJ是一个基于Java语言的AOP框架
Spring2.0以后新增了对AspectJ切点表达式支持
@AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面
新版本Spring框架,建议使用AspectJ方式来开发AOP

AspectJ表达式

  在Spring AOP中,要使用AspectJ的切点表达式语言来定义切点。关于Spring AOP的AspectJ切点,最重要的一点就是Spring仅支持AspectJ切点指示器(pointcut designator)的一个子集。Spring是基于代理的,而某些切点表达式是与基于代理的AOP无关的。Spring AOP所支持的AspectJ切点指示器如下:

在Spring中尝试使用AspectJ其他指示器时,将会抛出IllegalArgument-Exception异常。当我们查看如上所展示的这些Spring支持的指示器时,注意只有execution指示器是实际执行匹配的,而其他的指示器都是用来限制匹配的。这说明execution指示器是我们在编写切点定义时最主要使用的指示器。在此基础上,我们使用其他指示器来限制所匹配的切点。

execution 表达式语法:

execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)


  我们使用execution()指示器选择Performanceperform()方法。方法表达式以“*”号开始,表明了我们不关心方法返回值的类型。然后,我们指定了全限定类名和方法名。对于方法参数列表,我们使用两个点号(..)表明切点要选择任意的perform()方法,无论该方法的入参是什么。

  请注意我们使用了“&&”操作符把execution()within()指示器连接在一起形成与(and)关系(切点必须匹配所有的指示器)。类似地,我们可以使用“||”操作符来标识或(or)关系,而使用“!”操作符来标识非(not)操作。
  因为“&”在XML中有特殊含义,所以在Spring的XML配置里面描述切点时,我们可以使用and 来代替“&&”。同样,ornot可以分别用来代替“||”“!”

AspectJ增强:

  • @Before 前置通知,相当于BeforeAdvice
  • @AfterReturning 后置通知,相当于AfterReturningAdvice
  • @Around 环绕通知,相当于MethodInterceptor
  • @AfterThrowing抛出通知,相当于ThrowAdvice
  • @After 最终final通知,不管是否异常,该通知都会执行
  • @DeclareParents 引介通知,相当于IntroductionInterceptor (了解)

开发步骤

开发之前需要引入依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
基于XML

第一步:编写被增强的类:

 public class ProductDao {
public int add(){
System.out.println("添加商品...");
int d = 10/0;
return 100;
}
public void update(){
System.out.println("修改商品...");
}
public void delete(){
System.out.println("删除商品...");
}
public void find(){
System.out.println("查询商品...");
}
}

第二步:定义切面

import org.aspectj.lang.ProceedingJoinPoint;
/**
* 切面类
* @author hao
*
*/
public class MyAspectXML { public void before(){
System.out.println("前置通知...");
} public void afterReturing(Object returnVal){
System.out.println("后置通知...返回值:"+returnVal);
} public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("环绕前增强....");
Object result = proceedingJoinPoint.proceed();
System.out.println("环绕后增强....");
return result;
} public void afterThrowing(Throwable e){
System.out.println("异常通知..."+e.getMessage());
}
public void after(){
System.out.println("最终通知....");
}
}

第三步:配置applicationContext.xml

<!-- 定义目标对象 -->
<bean id="productDao" class="com.hao.aop.aspectj.xml.ProductDao"></bean> <!-- 定义增强 -->
<bean id="myAspectXML" class="com.hao.aop.aspectj.xml.MyAspectXML"></bean> <aop:config>
<!-- 定义切点: -->
<aop:pointcut id="mypointcut" expression="execution(* com.hao.aop.aspectj.xml.ProductDao.add(..))" />
<aop:aspect ref="myAspectXML">
<!-- 前置通知 -->
<aop:before method="before" pointcut-ref="mypointcut"/>
<!-- 后置通知 -->
<aop:after-returning method="afterReturing" pointcut-ref="mypointcut" returning="returnVal"/> <!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="mypointcut"/> <!-- 异常通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="mypointcut" throwing="e"/>
<!-- 最终通知 -->
<aop:after method="after" pointcut-ref="mypointcut"/>
</aop:aspect>
</aop:config>
基于注解

第一步:导入aop模块;Spring AOP:(spring-aspects)
第二部:定义一个业务逻辑类:在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)

public class UserDao {
public void add(){
System.out.println("添加用户");
}
public int update(){
System.out.println("修改用户");
return 1;
}
public void delete(){
System.out.println("删除用户");
}
public void find(){
System.out.println("查询用户");
//int d = 1/ 0;
}
}

第三步:定义一个切面类:切面类里面的方法需要动态感知业务类的方法运行到哪里然后执行;

  1. 给切面类的目标方法标注何时何地运行(通知注解);
  2. 必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
/**
* 切面类:就是切点与增强结合
*
* @author hao
*
*/
@Aspect
public class MyAspect { // 定义一个切点
@Pointcut("execution(* com.hao.aop.aspectj.anno.UserDao.find(..))")
private void myPointcut() {} // 此方法没有实际的意义,就是为了提供给注解一个修饰的地方 @Before("execution(* com.hao.aop.aspectj.anno.UserDao.add(..))")
public void before(JoinPoint joinPoint) {
System.out.println("前置增强...." + joinPoint);
} @AfterReturning(value = "execution(* com.hao.aop.aspectj.anno.UserDao.update(..))", returning = "returnVal")
public void afterReturin(Object returnVal) {
System.out.println("返回增强....方法的返回值:" + returnVal); } @Around(value = "MyAspect.myPointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕前增强....");
Object obj = proceedingJoinPoint.proceed();
System.out.println("环绕后增强....");
return obj;
}
@AfterThrowing(value = "MyAspect.myPointcut()", throwing = "e")
public void afterThrowing(Throwable e) {
System.out.println("不好了 出异常了!!!" + e.getMessage());
} @After("MyAspect.myPointcut()")
public void after() {
System.out.println("最终/后置通知...");
} }

AspectJ的通知类型:

  • 前置通知(@Before):logStart:在目标方法(div)运行之前运行
  • 后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)
  • 返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行
  • 异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行
  • 环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
  • 引介通知(@DeclareParents) ,相当于IntroductionInterceptor (不要求掌握)

切点的定义:

// 定义一个切点
@Pointcut("execution(* com.hao.aop.aspectj.anno.UserDao.find(..))")
private void myPointcut() {} // 此方法没有实际的意义,就是为了提供给注解一个修饰的地方

Advisor和Aspect的区别?

  • Advisor:Spring传统意义上的切面:支持一个切点和一个通知的组合.
  • Aspect:可以支持多个切点和多个通知的组合.

第四步:开启注解,并将切面类和业务逻辑类(目标方法所在类)都加入到容器中

XML方式:

<!-- 自动生成代理  底层就是AnnotationAwareAspectJAutoProxyCreator -->
<aop:aspectj-autoproxy /> <bean id="userDao" class="com.hao.aop.aspectj.anno.UserDao"></bean>
<bean id="myAspect" class="com.hao.aop.aspectj.anno.MyAspect"></bean>

注解方式

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy; @EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAOP {
//业务逻辑类加入容器中
@Bean
public UserDao userDao(){
return new UserDao();
}
//切面类加入到容器中
@Bean
public MyAspect myAspect(){
return new MyAspect();
}
}

测试

  • 注意加载的配置文件
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=MainConfigOfAOP.class)
//此处的配置文件可以加载java类 或者 XML文件
//@ContextConfiguration("classpath:contextApplication5.xml")
public class AOPTest2 { @Autowired
@Qualifier("userDao")
private UserDao userDao;
@Test
public void demo1(){
userDao.add();
userDao.delete();
userDao.update();
userDao.find();
}
}

  给配置类中加@EnableAspectJAutoProxy【开启基于注解的aop模式】,在Spring中很多的 @EnableXXX(要抽时间整理一下其原理);

总结
  1. 将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个是切面类(@Aspect)
  2. 在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)
  3. 开启基于注解的aop模式;@EnableAspectJAutoProxy

6. AOP的实现机制原理(AnnotationAwareAspectJAutoProxyCreator)

AnnotationAwareAspectJAutoProxyCreator 底层的原理

已经整理完,查阅【Spring】AOP注解方式实现机制

【Spring】 AOP Base的更多相关文章

  1. 【Spring】AOP注解方式实现机制

    一.概述 二.@EnableAspectJAutoProxy 注解分析 三.分析AnnotationAwareAspectJAutoProxyCreator 四.执行流程 1. registerBea ...

  2. 【Spring】AOP实现原理(三):创建代理

    AbstractAutoProxyCreator 在AbstractAutoProxyCreator的wrapIfNecessary方法中,调用getAdvicesAndAdvisorsForBean ...

  3. 【Spring】AOP实现原理(一):AOP基础知识

    AOP相关概念 在学习AOP实现原理之前,先了解下AOP相关基础知识. AOP面向切面编程,它可以通过预编译方式或者基于动态代理对我们编写的代码进行拦截(也叫增强处理),在方法执行前后可以做一些操作, ...

  4. 【Spring】 IOC Base

    一.关于容器 1. ApplicationContext和BeanFactory 2. 配置文件 XML方式 Java-configuration 方式 @Configuration 3. 初始化容器 ...

  5. 【Spring】AOP的代理默认是Jdk还是Cglib?

    菜瓜:你觉得AOP是啥 水稻:我觉得吧,AOP是对OOP的补充.通常情况下,OOP代码专注功能的实现,所谓面向切面编程,大多数时候是对某一类对象的方法或者功能进行增强或者抽象 菜瓜:我看你这个理解就挺 ...

  6. 【Spring】AOP实现原理(二):Advisor获取

    @EnableAspectJAutoProxy @EnableAspectJAutoProxy注解可以用来开启AOP,那么就从@EnableAspectJAutoProxy入手学习一下Spring A ...

  7. 【spring】aop切面通知,日志处理

    1.spring的切面编程 概念原理可以看这里:http://blog.csdn.net/moreevan/article/details/11977115 2.所需要的jar包 maven引入jar ...

  8. 【Spring】AOP

    AOP 编程允许你把遍布应用各处的功能分离出来形成可重用的组件,将安全.事务和日志关注点与你的核心业务逻辑相分离. 面向切面编程往往被定义为促使应用程序分离关注点的一项技术.系统由许多不同组件组成,每 ...

  9. 【AOP】操作相关术语---【Spring】的【AOP】操作(基于aspectj的xml方式)

    [AOP]操作相关术语 Joinpoint(连接点):类里面哪些方法可以被增强,这些方法称为连接点. Pointcut(切入点):在类里面可以有很多的方法被增强,比如实际操作中,只是增强了类里面add ...

随机推荐

  1. Hadoop 系列(七)—— HDFS Java API

    一. 简介 想要使用 HDFS API,需要导入依赖 hadoop-client.如果是 CDH 版本的 Hadoop,还需要额外指明其仓库地址: <?xml version="1.0 ...

  2. 如何阅读JDK源码

    JDK源码阅读笔记: https://github.com/kangjianwei/LearningJDK 如何阅读源码,是每个程序员需要面临的一项挑战. 为什么需要阅读源码?从实用性的角度来看,主要 ...

  3. c++/c关于函数指针

    顺便提一句:指针也是一种变量类型 和 int double 这些类型是一个级别 不同的是它的值是地址 #include "stdafx.h"#include<stdlib.h ...

  4. Java学习多线程第二天

    内容介绍 线程安全 线程同步 死锁 Lock锁 等待唤醒机制 1    多线程 1.1     线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果 ...

  5. hadoop学习(二)----HDFS简介及原理

    前面简单介绍了hadoop生态圈,大致了解hadoop是什么.能做什么.带着这些目的我们深入的去学习他.今天一起看一下hadoop的基石--文件存储.因为hadoop是运行与集群之上,处于分布式环境之 ...

  6. xpath爬虫实例,爬取图片网站百度盘地址和提取码

    某套图网站,套图以封面形式展现在页面,需要依次点击套图,点击广告盘链接,最后到达百度网盘展示页面. 这一过程通过爬虫来实现,收集百度网盘地址和提取码,采用xpath爬虫技术 1.首先分析图片列表页,该 ...

  7. 减谈迷宫C++

    今天老师让做了个迷宫问题,我一看到就发现和我之前写过的一个程序是一样 的,但是在后来编写的时候有一个地方搞错了,最后下课了我还是没有正确的编写好,然后今天回来之后自己有看了一下,现在已经解决了. #i ...

  8. CentOS7.x 搭建 GitLab 教程

    今天闲来无事,想起之前买了一个阿里云 ECS,一直闲置着没用,一时兴起就想搭个自己的 GitLab 玩玩,GitLab 官网也提供了安装教程,很简单,照着步骤一步步基本没什么问题,可能安装的过程中有一 ...

  9. 小白学Python(3)——输入和输出,显示你的名字

    任何计算机程序都是为了执行一个特定的任务,有了输入,用户才能告诉计算机程序所需的信息,有了输出,程序运行后才能告诉用户任务的结果. 输入是Input,输出是Output,因此,我们把输入输出统称为In ...

  10. 解决MobaXterm-SSH中文乱码问题

    一般情况不用修改服务器字符集(linux或unix服务器字符集一般不会设置错误). 1.首先用命令查看当前系统的LANG是什么: >locale LANG=en_US LC_COLLATE=&q ...