AOP小结1

一、AOP的概念

AOP:面向切面编程,基于IOC。
AOP技术简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,减少系统的重复代码,降低模块之间的耦合度,并有利于可维护性。

1、切面(aspect)
系统各处的通用的业务逻辑代码,如日志模块、权限模块、事务模块等。切面用来装载pointcut和advice
2、通知(advice)
指拦截到连接点之后要执行的代码。分为前置、后置、异常、最终、环绕通知五类。
3、连接点(joinpoint)
被拦截到的点,Spring只支持方法类型的连接点,在Spring中连接点指的就是被拦截到的方法。
4、切入点(pointcut)
拦截的方法,连接点拦截后变成切入点。
5、目标对象(Target Object)
代理的目标对象,指要织入的对象模块。
7、织入(weave)
通过切入点切入,将切面应用到目标对象并导致代理对象创建的过程。
8、AOP代理(AOP Proxy)
AOP框架创建的对象,包含通知。在Spring中,AOP代理可以是JDK动态代理或CGLIB代理。

五种类型的通知

  1. 前置(Before advice):在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。 < aop:before>
  2. 后置(After advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。 < aop:after>
  3. 最终(After returnadvice):在某连接点正常完成后执行的通知,不包括抛出异常的情况。 < aop:after-returning>
  4. 环绕(Around advice):包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法执行的前后实现逻辑,也可以选择不执行方法 < aop:around>
  5. 异常(Afterthrowing advice):在方法抛出异常退出时执行的通知。 < aop:after-throwing>

Spring AOP 使用步骤

1、定义具体业务逻辑模块(目标对象)
2、定义切面(实现通知逻辑)
3、实现切面逻辑

基于Schema的Spring AOP实例

1.定义具体业务逻辑模块(目标对象)

public class TestAOPDaoImpl implements TestAOPDao{
    @Override
    public void addUser() {
        System.out.println("添加成功");
    }
}

2 .定义切面(即实现通知逻辑)

日志切面

public class TestAOPServiceImpl implements TestAOPService{
    @Autowired
    private TestAOPDao testAOPDao;
    @Override
    public void addUser() {
        testAOPDao.addUser();
    }
}
public class LogAdivice{
    public void myBeforeAdivice(JoinPoint joinPoint){
        String classname = joinPoint.getTarget().getClass().getSimpleName();
        String methodname = joinPoint.getSignature().getName();
        System.out.println(classname + " ——前置通知——" + methodname);
    }
    public void myAfterAdivice(JoinPoint joinPoint){
        String classname = joinPoint.getTarget().getClass().getSimpleName();
        String methodname = joinPoint.getSignature().getName();
        System.out.println(classname + " ——后置通知——" + methodname);
    }
    /**
     * 环绕通知将决定要不要执行连接点
     * @throws Throwable 
     */
    public void myAroundAdivice(ProceedingJoinPoint point) throws Throwable{
        System.out.println("环绕通知,执行代码前");
        //选择执行
        point.proceed();
        System.out.println("环绕通知,执行代码后");
    }
}

时间切面:

public class TimeAdvice {
    public void timeBefore(){
        System.out.println("beforeTime = " + System.currentTimeMillis());
    }
    public void timeAfter(){
        System.out.println("afterTime = " + System.currentTimeMillis());
    }
}

在applicationContext中配置切面:


    
    
    
    
    
       
       
           
           
           
           
           
           
           
           
       
       
       
           
           
           
           
           
           
       
    

测试结果

public class AOPTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        TestAOPService service = (TestAOPService) context.getBean("testAOPService");
        service.addUser();
    }
}

基于@AspectJ注解的AOP实现

1.定义具体业务逻辑模块(目标对象)

public class TestAOPDaoImpl implements TestAOPDao{
    @Override
    public void addUser() {
        System.out.println("添加成功");
    }
}

public class TestAOPServiceImpl implements TestAOPService{
    @Autowired
    private TestAOPDao testAOPDao;
    @Override
    public void addUser() {
        testAOPDao.addUser();
    }
}

2.定义切面(即实现通知逻辑)

@Aspect
public class LogAdivice{
    //定义一个方法作为切入点id
    @Pointcut("execution(* com.ssh.service.TestAOPService.*(..))")
    private void allMethod(){}
    @Before("allMethod()")
    public void myBeforeAdivice(JoinPoint joinPoint){
        String classname = joinPoint.getTarget().getClass().getSimpleName();
        String methodname = joinPoint.getSignature().getName();
        System.out.println(classname + " ——前置通知——" + methodname);
    }
    @AfterReturning("allMethod()")
    public void myAfterAdivice(JoinPoint joinPoint){
        String classname = joinPoint.getTarget().getClass().getSimpleName();
        String methodname = joinPoint.getSignature().getName();
        System.out.println(classname + " ——后置通知——" + methodname);
    }
    /**
     * 环绕通知将决定要不要执行连接点
     * @throws Throwable 
     */
    @Around("allMethod()")
    public void myAroundAdivice(ProceedingJoinPoint point) throws Throwable{
        System.out.println("环绕通知,执行代码前");
        //执行
        point.proceed();
        System.out.println("环绕通知,执行代码后");
    }
}

在applicationContext的配置:


    
    
    
    
    
    
    
    

Java代码使用AOP

public class TestControlFlowPointcut {
    public static void main(String[] args) {
        //只有TargetCaller中的方法才会被拦截
        ControlFlowPointcut pointcut = new ControlFlowPointcut(TargetCaller.class);
        BeforeAdvice beforeAdvice = new MethodBeforeAdvice() {
            public void before(Method method, Object[] objects, Object o) throws Throwable {
                System.out.println(method.getClass().getSimpleName() + ":" +
                        method.getName() + " - before logic ");
            }
        };
        // Spring 中的 Aspect,装载pointcut和advice
        PointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, beforeAdvice);
        // Spring 基本织入器weaver
        ProxyFactory weaver = new ProxyFactory();
        weaver.setTarget(new TargetObject());   //指定代理目标对象
        weaver.addAdvisor(advisor);  //指定方面
        Object proxy = weaver.getProxy();
        //直接调用Targetobject的方法不会被拦截
        ((TargetObject)proxy).targetMethod();
        //使用ControlFlowPointcut指定的类中的方法才会被拦截
        TargetCaller caller = new TargetCaller();
        caller.setTarget((TargetObject)proxy);
        caller.callMethod();
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(AOP小结1)