ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SpringAop代理详解

2019-03-27 15:53:39  阅读:221  来源: 互联网

标签:target System 代理 println 详解 SpringAop public out


1.AOP是什么? 面向切面编程,能够让我们在不影响原有功能的前提下,为软件横向扩展 功能 .

2.在什么地方能够让我们少写代码? 要回答问题2,首先解决"横向"扩展什么意思? 理解了这个词基本就能理解AOP了. 软件开发可分为"持久层" “业务层” 控制器层" 所谓的"横向"就是指上面说到的三个层里的任意一层!
使用AOP技术后,用一个方法,就能同时作用与一个层面内所有方法!
AOP的作用
  在OOP中,正是这种分散在各处且与对象核心功能无关的代码(横切代码)的存在,使得模块复用难度增加。AOP则将封装好的对象剖开,找出其中对多个对象产生影响的公共行为,并将其封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),切面将那些与业务无关,却被业务模块共同调用的逻辑提取并封装起来,减少了系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。

应用场景:
权限控制 缓存控制 事务控制 审计日志 性能监控 分布式追踪 异常处理

AOP代理
分为静态代理和动态代理

1.目标接口
public interface ProductService {
       
       public void save();
}

2.接口实现类
public class ProductImpl implements ProductService {
       @Override
       public void save() {
             // TODO Auto-generated method stub
                    System.out.println("模拟保存");         
       }
}

3.代理类实现目标接口
public class ProductDaoProxy implements ProductService {
       private ProductService productService=new ProductImpl();
       @Override
       public void save() {
             // TODO Auto-generated method stub
             System.out.println("代理前做。。");
             productService.save();
             System.out.println("代理后做。。");
       }
}
4.main中
       public static void main(String[] args) {
             //静态代理
           ProductService proxy=new ProductDaoProxy(); 
           proxy.save();
}

缺点:
静态代理虽然保证了业务类只需关注逻辑本身,代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,
势必要为每一种方法都进行代理。再者,如果增加一个方法,除了实现类需要实现这个方法外,所有的代理类也要实现此方法。
增加了代码的维护成本。那么要如何解决呢?答案是使用动态代理。

动态代理

1.目标接口
public interface PersonService {
       public void get();
}
public interface ProductService {
       
       public void save();
}
2.接口实现类
public class PersonImpl implements PersonService {
       @Override
       public void get() {
             // TODO Auto-generated method stub
             System.out.println("模拟查询");
       }
       
}
public class ProductImpl implements ProductService {
       @Override
       public void save() {
             // TODO Auto-generated method stub
                    System.out.println("模拟保存");         
       }
}
3.代理工厂
public class ProxyFactory implements InvocationHandler {
       public Object target;
       public ProxyFactory(Object target) {
             // TODO Auto-generated constructor stub
             this.target=target;
       }
       
       public Object getProxyInstance()
       {
             Object object=Proxy.newProxyInstance(//传入3个参数
                           target.getClass().getClassLoader() //目标对象使用的类加载器
                           , target.getClass().getInterfaces() //目标对象实现的所有接口
                           ,new ProxyFactory(target));
                    return object;             
       }                          
 
       @Override
       public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
             // TODO Auto-generated method stub
             Object result=null;
             String methodName=method.getName();
             System.out.println("方法名:"+methodName);
             if(methodName.equals("save"))
             {
                     System.out.println("开启事务...");
                     result=method.invoke(target, args); //调用 save方法
                     System.out.println("提交事务...");
                    
             }if(methodName.equals("get"))
             {
                    System.out.println("开启事务1...");
                     result=method.invoke(target, args);// 调用 get方法
                     System.out.println("提交事务1...");
             }
             return result;
       }
}

4.main
//创建目标对象
             ProductService target=new ProductImpl();
             PersonService target1=new PersonImpl();
             System.out.println("目标对象:"+target.getClass());
             //创建代理对象
             ProductService proxy=(ProductService) new ProxyFactory(target).getProxyInstance();
             System.out.println("代理对象:"+proxy.getClass());
             proxy.save();
             
             System.out.println("目标对象:"+target1.getClass());
             //创建代理对象
             PersonService proxy1= (PersonService) new ProxyFactory(target1).getProxyInstance();
             System.out.println("代理对象:"+proxy1.getClass());
             proxy1.get();

运行结果 :
在这里插入图片描述解释:
在构造方法中接受一个目标对象,通过代理工厂动态生成一个实现了目标接口的类,这个实现类我们并没有写由这个工厂构造出来
在这里插入图片描述
如图可见生成了一个 com.sun…&Proxy0的代理对象

Proxy.newProxyInstance:
这是 java.lang.reflect.Proxy包下的 该类用于动态生成代理类,只需传入目标接口、目标接口的类加载器以及InvocationHandler便可为目标接口生成代理类及代理对象。

public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException

loader: 用哪个类加载器去加载代理对象
interfaces:动态代理类需要实现的接口
h:动态代理方法在执行时,会调用h里面的invoke方法去执行

知道了什么是动态代理 sping实战 基于xml配置

xml:
<?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:context="http://www.springframework.org/schema/context"
    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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
  <!-- dao实例加入容器 -->
  <bean id="personImpl" class="com.example.demo.serviceImpl.PersonImpl"></bean>
 
  <!-- 实例化切面类 -->
  <bean id="transactionAop" class="com.example.demo.ascept.TransactionAop"></bean>
 
  <!-- Aop相关配置 -->
  <aop:config>
    <!-- 切入点表达式定义 -->
    <aop:pointcut expression="execution(* com.example.demo.serviceImpl.PersonImpl.get(..))" id="transactionPointcut"/>
    <!-- 切面配置 -->
    <aop:aspect ref="transactionAop">
      <!-- 【环绕通知】 -->
      <aop:around method="arroud" pointcut-ref="transactionPointcut"/>
      <!-- 【前置通知】 在目标方法之前执行 -->
      <aop:before method="beginTransaction" pointcut-ref="transactionPointcut" />
      <!-- 【后置通知】 -->
      <aop:after method="commit" pointcut-ref="transactionPointcut"/>
      <!-- 【返回后通知】 -->
      <aop:after-returning method="afterReturing" pointcut-ref="transactionPointcut"/>
      <!-- 异常通知 -->
      <aop:after-throwing method="afterThrowing" pointcut-ref="transactionPointcut"/>
    </aop:aspect>
  </aop:config>
</beans>



private ApplicationContext ac=new ClassPathXmlApplicationContext("springAop.xml",getClass()); //引入xml
       public static void main(String[] args) {
             SpringAopApplication springAopApplication=new SpringAopApplication();
             springAopApplication.p();
}
public void p()
       {
             PersonService pService=(PersonService) ac.getBean("personImpl");
             pService.get();
             pService.save();
       }

execution(* com.example.demo.serviceImpl.PersonImpl.get(…)
execution组成
返回值+包名+类名+方法(任意参数)
第一个*代表返回值 *代表返回任意对象
aop表达式详解请看这篇:https://www.cnblogs.com/haore147/p/7212504.html

Spring中的AOP代理还是离不开Spring的IOC容器,代理的生成,管理及其依赖关系都是由IOC容器负责,Spring默认使用JDK动态代理,在需要代理类而不是代理接口的时候,Spring会自动切换为使用CGLIB代理,不过现在的项目都是面向接口编程,所以JDK动态代理相对来说用的还是多一些。

标签:target,System,代理,println,详解,SpringAop,public,out
来源: https://blog.csdn.net/weixin_43410352/article/details/88846206

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有