切面(aop)控制反转和依赖注入(IOC,DI)和spring的事务隔离和传播行为

前端之家收集整理的这篇文章主要介绍了切面(aop)控制反转和依赖注入(IOC,DI)和spring的事务隔离和传播行为前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

实现AOP,主要通过两类方式:

1.采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;

2.采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间输入有关“方面”的代码

方式不同效果却相同,具有的特性也是相同的:

·连接点(join point):是程序执行中的一个精确执行点,例如类中的一个方法。它是一个抽象的概念,在实现AOP时,并不需要去定义一个join point。

·切入点(point cut):本质上是一个捕获连接点的结构。在AOP中,可以定义一个point cut,来捕获相关方法调用

·通知(advice):是point cut的执行代码,是执行“方面”的具体逻辑。

·方面(aspect):point cut和advice结合起来就是aspect,它类似于OOP中定义的一个类,但它代表的更多是对象间横向的关系。

·引入(introduce):为对象引入附加的方法属性,从而达到修改对象结构的目的。有的AOP工具又将其称为mixin。

AOP适用于如下功能

·安全验证(Authentication )

·缓存(Caching )

·上下文传递(Context passing )

·错误处理(Error handling )

·后期加载(Lazy loading) 

·调试(Debugging)

·记录、跟踪、优化和监测(logging,tracing,profiling and monitoring) 

·性能优化(Performance optimization) 

·持久化(Persistence)

·资源池(Resource pooling) 

·同步(Synchronization) 

·事务(Transactions)

eg:

  1. //定义接口
  2. package com.greysh.aop.service;
  3.  
  4. public interface HelloWorld {
  5.  
  6. public void say();
  7. }
  8.  
  9. //对应的实现为
  10. package com.greysh.aop.service.impl;
  11.  
  12. import com.greysh.aop.service.HelloWorld;
  13.  
  14. public class HelloWorldImpl implements HelloWorld {
  15.  
  16. public void say() {
  17.  
  18. System.out.println("Say HelloWorld");
  19. }
  20. }
  21. //程序调用的时候
  22. package com.greysh.aop.test;
  23.  
  24. import com.greysh.aop.factory.ProxyFactory;
  25. import com.greysh.aop.service.HelloWorld;
  26. import com.greysh.aop.service.impl.HelloWorldImpl;
  27.  
  28. public class TestHelloWorld {
  29.  
  30. public static void main(String[] args) {
  31.  
  32. HelloWorld mb = new HelloWorldImpl();
  33. HelloWorld bi = (HelloWorld) ProxyFactory.getProxy(mb);
  34. bi.say();
  35. }
  36. }
  37.  
  38. //工厂
  39. package com.greysh.aop.factory;
  40.  
  41. import java.lang.reflect.Proxy;
  42. import com.greysh.aop.proxy.ProxyHandler;
  43.  
  44. public class ProxyFactory {
  45.  
  46. public static Object getProxy(Object obj) {
  47.  
  48. ProxyHandler bn = new ProxyHandler();
  49. bn.setTarget(obj);
  50. return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),bn);
  51. }
  52. }
  53.  
  54. //代理和反射类
  55. package com.greysh.aop.proxy;
  56.  
  57. import java.lang.reflect.InvocationHandler;
  58. import java.lang.reflect.Method;
  59.  
  60. public class ProxyHandler implements InvocationHandler {
  61.  
  62. private Object target;
  63. public void setTarget(Object target) {
  64.  
  65. this.target = target;
  66. }
  67.  
  68. @Override
  69. public Object invoke(Object proxy,Method method,Object[] args) throws Throwable {
  70.  
  71. System.out.println("Before Helloworld");
  72.  
  73. @SuppressWarnings("unused")
  74. Object result = method.invoke(target,args);
  75. System.out.println("Finish Helloworld");
  76. return null;
  77. }
  78. }
  79.  
  80. //程序运行时候的结果是
  81.  
  82. Before Helloworld
  83.  
  84. Say HelloWorld
  85.  
  86. Finish Helloworld
  87.  
  88. 如果不是用AOP,那么打印的结果
  89.  
  90. Say HelloWorld
  91.  
  92. 5文件构成一个最简单的AOPDEMO
  93. 类似Struts2拦截
  94. 如果两个类实现同一个接口,但是用的时候用一个类代替另一个类,这就是代理模式
  95. 上述就用了代理模式
  96.  
  97. 当我们调用bi.say(),其实并不是直接用HelloWorldImplsay(),
  98.  
  99. 而是
  100.  
  101. HelloWorld bi = (HelloWorld) ProxyFactory.getProxy(mb);
  102. 这样ProxyFactory先用ProxyHandler将对象赋值,这里需要调用reflect包,重写里面的invoke方向,这里的invoke调用的时候先执行
  103. System.out.println("Before Helloworld");
  104.  
  105.  
  106. 然后用反射
  107. Object result = method.invoke(target,args);

控制反转(IOC)和依赖注入(DI)

IoC 是一个很大的概念,可以用不同的方式来实现。其主要实现方式有两种: <1>依赖查找(Dependency Lookup 容器提供回调接口和上下文环境给组件 EJB Apache Avalon 都使用这种方式。 <2>依赖注入(Dependency Injection :组件不做定位查询,只提供普通的 Java 方法让容器去决定依赖关系。后者是时下最流行的 @H_301_143@类型,其又有接口注入( Interface Injection ),设值注入( Setter Injection )和构造子注入( Constructor Injection )三种方式。
eg:
依赖查找
  1. public class MyBusniessObject{
  2. private DataSource ds;
  3. private MyCollaborator myCollaborator;
  4. public MyBusnissObject(){
  5. Context ctx = null;
  6. try{
  7. ctx = new InitialContext();
  8. ds = (DataSource) ctx.lookup(“java:comp/env/dataSourceName”);
  9. myCollaborator =
  10. (MyCollaborator) ctx.lookup(“java:comp/env/myCollaboratorName”);
  11. }……
代码展示了基于 JNDI 实现的依赖查找机制,依赖查找的主要问题是,这段代码必须依赖于JNDI环境,所以它不能在应用服务器之外运行,并且如果要用别的方式取代@H_301_143@来查找资源和协作对象,就必须把@H_301_143@代码抽出来重构到一个策略方法中去。
依赖注入:
待注入对象
  1. package com.senssic;
  2. public class Content {
  3. public void BusniessContent(){
  4. System.out.println("do business");
  5. }
  6. public void AnotherBusniessContent(){
  7. System.out.println("do another business");
  8. }
  9. }
构造子注入( @H_301_143@)
  1. public class MyBusiness {
  2. private Content myContent;
  3. public MyBusiness(Content content) {
  4. myContent = content;
  5. }
  6. public void doBusiness(){
  7. myContent.BusniessContent();
  8. }
  9. public void doAnotherBusiness(){
  10. myContent.AnotherBusniessContent();
  11. }
  12. }

设值注入(Setter Injection
  1. public class MyBusiness {
  2. private Content myContent;
  3. public void setContent(Content content) {
  4. myContent = content;
  5. }
  6. public void doBusiness(){
  7. myContent.BusniessContent();
  8. }
  9. public void doAnotherBusiness(){
  10. myContent.AnotherBusniessContent();
  11. }
  12. }


接口注入(Interface Injection
设置接口
  1. public interface InContent {
  2. void createContent(Content content);
  3. }
接口注入
  1. public class MyBusiness implements InContent{
  2. private Content myContent;
  3. public void createContent(Content content) {
  4. myContent = content;
  5. }
  6. public void doBusniess(){
  7. myContent.BusniessContent();
  8. }
  9. public void doAnotherBusniess(){
  10. myContent.AnotherBusniessContent();
  11. }
  12. }

spring的事务隔离级别和传播行为

Spring在TransactionDefinition接口中定义这些属性

在TransactionDefinition接口中定义了五个不同的事务隔离级别
ISOLATION_DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应
ISOLATION_READ_UNCOMMITTED 这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读
ISOLATION_READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
ISOLATION_REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。

在TransactionDefinition接口中定义了七个事务传播行为。 PROPAGATION_required 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。 PROPAGATION_SUPPORTS 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务管理器,PROPAGATION_SUPPORTS与不使用事务有少许不同。 PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。 PROPAGATION_REQUIRES_NEW 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。 PROPAGATION_NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务。 PROPAGATION_NEVER 总是非事务地执行,如果存在一个活动事务,则抛出异常 PROPAGATION_NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务,则按TransactionDefinition.PROPAGATION_required 属性执行

猜你在找的设计模式相关文章