AOP

切面编程,实现切面插入,让代码更加灵活。

1.继承实现

新建一个接口:

public interface UserService {
    public abstract void syso();
    
}

来个实现类,

public class ExtendAOP extends UserServiceImpl {
    
    /** 通过继承方式实现aop切面插入。
     *  缺点:只能单继承。
     */
    @Override
    public void syso() {
        System.out.println("开始切入");
        super.syso();
        System.out.println("切入完毕");
    }
    
}

测试:

@org.junit.Test
    public void test(){
        ExtendAOP aop=new ExtendAOP();
        aop.syso();
    }

结果:

开始切入
打印日志
切入完毕

 

2.静态代理模式,接口加多一个方法。

public interface UserService {
    public abstract void print();
    public void syso();

}

实现:

public class Proxy implements UserService {
    /**
     * 静态代理,通过实现接口的方式,但是同样要创建实例,没有动态代理。
     */
    UserServiceImpl userServiceImpl = new UserServiceImpl();
    @Override
    public void print() {
        
    }
    @Override
    public void syso() {
        System.out.println("开始切入");
        userServiceImpl.syso();
        System.out.println("切入完毕");
    }
}

测试:

@org.junit.Test
    public void proxy(){
        Proxy proxy=new Proxy();
        proxy.syso();
    }

结果:

开始切入
打印日志
切入完毕

3.使用sping框架提供的aop插入功能,使用配置文件配置。

jar包

image

同样还是接口和接口的实现。…

配置文件加上

<!-- AOP配置文件写法 -->
          <bean id="logger" class="logger.Logger"></bean>
          <aop:config>
              <aop:pointcut expression="execution (* service.impl.User*.*(..))" id="aop"/><!-- 返回值 service.impl包下任意java,任意方法  参数随意  -->
              <aop:aspect ref="logger">
                  <aop:before method="before" pointcut-ref="aop"/>
                  <aop:after method="after" pointcut-ref="aop"/>
                  <aop:around method="logAround" pointcut-ref="aop"/>
                  <aop:after-returning method="afterReturning" pointcut-ref="aop"/>
              </aop:aspect>
          </aop:config>

其中bean 对应着相应的插入的类路径 ,aop:point 表示插入点,后面的表达式匹配要插入的地方。 aop:aspect插入面,对应着插入类,下面就是各个对应的方法该插入到那里。(注:这里是关键的配置,其他的没加上来。单元测试还要有获得对象的bean或者注解扫描包的配置。)

插入的实现类:Logger

public class Logger {
    public static void print(){
        System.out.println("打印日志");
    }
    public static void before(){
        System.out.println("-----before------");
    }
    public static void after(){
        System.out.println("-----after------");
    }
    /** 环绕 通知 */
    public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("---前--环绕日志--------");
        Object ret = pjp.proceed();// 执行目标方法相当于InvocationHandler
        System.out.println("---后--环绕日志--------");
        return ret;
    }
    public static void afterReturning(){
        System.out.println("-----after-returning------");
    }

}

测试:

@org.junit.Test
    public void Aop(){
        ApplicationContext context=new ClassPathXmlApplicationContext("application4.xml");
        UserService service= (UserService) context.getBean("userServiceImpl");
        service.syso();
    }

结果:(xml注释after、logAround、afterReturning)

-----before------
打印日志

 

4.用AOP注解了实现。

插入实现类:

@Aspect
@Component
public class LoggerByAnnotation {
    
    @Pointcut("execution(* service.impl.UserService2Impl.*(..))")
    private void anyMethod(){}
    
    @Before("
anyMethod()
")
    public static void before(){
        System.out.println("-----before------");
    }
    @After("
anyMethod()
")
    public static void after(){
        System.out.println("-----after------");
    }
    /** 环绕 通知 */
    @Around("
anyMethod()
")
    public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("----前--环绕日志--------");
        Object ret = pjp.proceed();// 执行目标方法相当于InvocationHandler
        System.out.println("----后--环绕日志--------");
        return ret;
    }
     @AfterReturning("
anyMethod()
")
    public static void afterReturning(){
        System.out.println("-----after-returning------");
    }
    public static void print() {
        System.out.println("gggggg");
    }

}

配置文件:

<!-- Aop注解的方式 -->
          <!-- AOP插入的类也要扫描一波 -->
          <context:component-scan base-package="logger"></context:component-scan>
          <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"></aop:aspectj-autoproxy>
          <!--  CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,
                  所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,
                  对于final方法,无法进行代理  -->

注意:pring中的切面类固然要用@Aspect标注,但也不要忘了用@Componet标注,这样才能被注册到容器中。

测试:

@org.junit.Test
    public void Aop(){
        ApplicationContext context=new ClassPathXmlApplicationContext("application4.xml");
        UserService2 service= (UserService2) context.getBean("userService2Impl");
        service.save();
    }

结果:

-----before------
打印日志

posted @ 2017-09-14 15:30  永恒之蓝  阅读(155)  评论(0编辑  收藏  举报