基于注解的AOP开发(AOP:Spring的动态代理开发)

一、首先回顾原始AOP开发流程

      

1.原始对象

2.额外功能

3.切入点

4.组装切面

二、基于注解的AOP开发

        #所需要的注解

       

# 通过切面类
	定义了 额外功能  @Around
	定义切入点   @Around("execution(* login(..))")
	@Aspect 将自定义的类指定为切面类

1、构建原始对象(service实现类)----实现核心功能代码

2、切面类的开发

@Apect
public class MyApect{

 @Around("execution(* login(..))")
    public Object  arround(ProceedingJoinPoint joinPoint)throws Throwable{
        System.out.println("前置增强的额外功能..........+++++++  事务管理功能----");
        Object ret = joinPoint.proceed();
        System.out.println("后置增强的额外功能.......++++++++  事务管理功能-------");
        return ret;
    }
    @Around("execution(* login(..))")
    public Object  arround1(ProceedingJoinPoint joinPoint)throws Throwable{
        System.out.println("前置增强的额外功能..........+++++++  性能监测-----");
        Object ret = joinPoint.proceed();
        System.out.println("后置增强的额外功能.......++++++++  性能监测-------");
        return ret;
    }
    @Around("execution(* login(..))")
    public Object  arround2(ProceedingJoinPoint joinPoint)throws Throwable{
        System.out.println("前置增强的额外功能..........+++++++ 日志功能 -----");
        Object ret = joinPoint.proceed();
        System.out.println("后置增强的额外功能.......++++++++  日志功能-------");
        return ret;
    }
}

2、配置文件的编写

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="userService" class="com.xxx.service.impl.UserServiceImpl"/>

<!--    将切面类交给工厂管理-->
    <bean id="arrount" class="com.xxx.aspect.MyAspect"></bean>
<!--告知Spring工厂基于注解进行AOP编程-->
    <aop:aspectj-autoproxy/>
</beans>

3、测试

 @Test
    public void testAspect(){
        ClassPathXmlApplicationContext c = new ClassPathXmlApplicationContext("/applicationContext3.xml");
        UserService arrount =(UserService) c.getBean("userService");
        arrount.login("ss","ss");
    }

 结果

4、冗余代码抽取

由第一版切面类可知---注解值切入点出现了重复性的使用

        简化切面类开发---抽取共性 ---使用 @Pointcut()标签

          

​
@Apect
public class MyApect{

  @Pointcut("execution(* login(..))")
    public void myPointCut(){}//指定切入点
    @Around(value="myPointCut()")
    public Object  arround(ProceedingJoinPoint joinPoint)throws Throwable{
        System.out.println("前置增强的额外功能..........+++++++  log-----");
        Object ret = joinPoint.proceed();
        System.out.println("后置增强的额外功能.......++++++++  log-------");
        return ret;
    }
    @Around(value="myPointCut()")
    public Object  arround1(ProceedingJoinPoint joinPoint)throws Throwable{
        System.out.println("前置增强的额外功能..........+++++++  性能监测-----");
        Object ret = joinPoint.proceed();
        System.out.println("后置增强的额外功能.......++++++++  性能监测-------");
        return ret;
    }
    @Around(value="myPointCut()")
    public Object  arround2(ProceedingJoinPoint joinPoint)throws Throwable{
        System.out.println("前置增强的额外功能..........+++++++  tx -----");
        Object ret = joinPoint.proceed();
        System.out.println("后置增强的额外功能.......++++++++  tx-------");
        return ret;
    }
}

​

 5、动态代理的创建方式

​
AOP的底层实现有两种实现方式
1.	基于JDK  通过实现接口,做新的实现类[动态生成的]    创建代理对象
2.	CGLIB   代理类通过继承原始类     完成代理对象的创建

默认情况下,AOP底层应用的是JDK动态代理创建方式
如果切换为 CGLIB
	1.传统的AOP开发[基于配置文件完成组装]      proxy-target-class="true"-----基于CGLIB   false[JDK]
	    <aop:config proxy-target-class="true">
            <!--定义切入点-->
            <aop:pointcut id="pc" expression="!execution(* login(..))"/>
            <aop:advisor advice-ref="myInterceptor" pointcut-ref="pc"/>
    	</aop:config>
    2.基于直接的AOP开发
    	<aop:aspectj-autoproxy proxy-target-class="true"/>   
    								proxy-target-class="true"-----基于CGLIB   false[JDK]

​

6、注意事项

        在同一个业务类中,进行业务方法间的调用时,只有最外层的方法,才会加入额外功能(内部方法时通过普通的方式在原始类中调取的,并没有加入额外功能)。如果想内层的方法也调用代理对象的方法,因该先获取代理对象,再调方法

        实现逻辑:

                1、使原始类实现ApplicationContextAware接口----它只有一个方法

                 2、实现接口中的方法

@Override
    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        this.ctx = ctx;
    }

            这里的this.ctx  我们需要设置一个ApplicationContext  ctx(变量名)  类型的属性

              这个方法的返回值就是Spring工厂对象,获取动态代理对象的方法我们可以通过getBean()方法来获取动态代理对象

原始类:

public class UserServiceImpl implements UserService, ApplicationContextAware {
    private ApplicationContext ctx;
    @Override
    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        this.ctx = ctx;
    }

    @Override
    public User login(String uname, String pwd) {
        System.out.println("UserServiceImpl ----- login(String uname,String pwd)...... 核心功能的编码");
        return new User();
    }
    @Log
    @Override
    public void regist(User user) {
        System.out.println("UserServiceImpl ----- regist(User user)...... 核心功能的编码");
    }

    @Override
    public User login(String name) {
        System.out.println("UserServiceImpl ----- login(String uname)...... 核心功能的编码");
        return new User();
    }
    /*
        工厂属于重量级资源,一个应用中应该只创建一个工厂-----》  等待外界传递 
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext2.xml");
         UserService service = ctx.getBean("userService", UserService.class); // 代理对象
         service.login("小黑","666666"); 
         
         代理对象需要借助于工厂
         	需要工厂!!!
         
        public void dropById(Integer id) {
        	this.login("小黑","666666"); // 当前目标对象的login方法 ------>更换为调用代理对象的login
        	System.out.println("dropById............. 核心功能的编码");
    }    
         
    */
    @Override
    public void dropById(Integer id) {
        UserService service = ctx.getBean("userService", UserService.class); // 代理对象
        service.login("小黑","666666"); 
        System.out.println("dropById............. 核心功能的编码");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值