切面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:

//定义接口
package com.greysh.aop.service;

public interface HelloWorld {

public void say();
}

//对应的实现为
package com.greysh.aop.service.impl;

import com.greysh.aop.service.HelloWorld;

public class HelloWorldImpl implements HelloWorld {

public void say() {

System.out.println("Say HelloWorld");
}
}
//程序调用的时候
package com.greysh.aop.test;

import com.greysh.aop.factory.ProxyFactory;
import com.greysh.aop.service.HelloWorld;
import com.greysh.aop.service.impl.HelloWorldImpl;

public class TestHelloWorld {

public static void main(String[] args) {

HelloWorld mb = new HelloWorldImpl();
HelloWorld bi = (HelloWorld) ProxyFactory.getProxy(mb);
bi.say();
}
}

//工厂
package com.greysh.aop.factory;

import java.lang.reflect.Proxy;
import com.greysh.aop.proxy.ProxyHandler;

public class ProxyFactory {

public static Object getProxy(Object obj) {

ProxyHandler bn = new ProxyHandler();
bn.setTarget(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),bn);
}
}

//代理和反射类
package com.greysh.aop.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ProxyHandler implements InvocationHandler {

private Object target;
public void setTarget(Object target) {

this.target = target;
}

@Override
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable {

System.out.println("Before Helloworld");

@SuppressWarnings("unused")
Object result = method.invoke(target,args);
System.out.println("Finish Helloworld");
return null;
}
}

//程序运行时候的结果是

Before Helloworld

Say HelloWorld

Finish Helloworld

如果不是用AOP,那么打印的结果

Say HelloWorld

  
  这5个文件构成一个最简单的AOP的DEMO
  类似Struts2的拦截器
  如果两个类实现同一个接口,但是用的时候用一个类代替另一个类,这就是代理模式
  上述就用了代理模式
   

当我们调用bi.say(),其实并不是直接用HelloWorldImpl的say(),

而是

HelloWorld bi = (HelloWorld) ProxyFactory.getProxy(mb);
这样ProxyFactory先用ProxyHandler将对象赋值,这里需要调用reflect包,重写里面的invoke方向,这里的invoke在调用的时候先执行
  
System.out.println("Before Helloworld");


然后用反射
Object result = method.invoke(target,args);
  

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

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

设值注入(Setter Injection
public class MyBusiness {
    private Content myContent;
 
    public void setContent(Content content) {
       myContent = content;
    }
   
    public void doBusiness(){
       myContent.BusniessContent();
    }
   
    public void doAnotherBusiness(){
       myContent.AnotherBusniessContent();
    }
}


接口注入(Interface Injection
设置接口
public interface InContent {
    void createContent(Content content);
}
接口注入
public class MyBusiness implements InContent{
    private Content myContent;
 
    public void createContent(Content content) {
       myContent = content;
    }
   
    public void doBusniess(){
       myContent.BusniessContent();
    }
   
    public void doAnotherBusniess(){
       myContent.AnotherBusniessContent();
    }
}

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 属性执行

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


什么是设计模式一套被反复使用、多数人知晓的、经过分类编目的、代码 设计经验 的总结;使用设计模式是为了 可重用 代码、让代码 更容易 被他人理解、保证代码 可靠性;设计模式使代码编制  真正工程化;设计模式使软件工程的 基石脉络, 如同大厦的结构一样;并不直接用来完成代码的编写,而是 描述 在各种不同情况下,要怎么解决问题的一种方案;能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免引
单一职责原则定义(Single Responsibility Principle,SRP)一个对象应该只包含 单一的职责,并且该职责被完整地封装在一个类中。Every  Object should have  a single responsibility, and that responsibility should be entirely encapsulated by t
动态代理和CGLib代理分不清吗,看看这篇文章,写的非常好,强烈推荐。原文截图*************************************************************************************************************************原文文本************
适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类可以相互合作。
策略模式定义了一系列算法族,并封装在类中,它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
设计模式讲的是如何编写可扩展、可维护、可读的高质量代码,它是针对软件开发中经常遇到的一些设计问题,总结出来的一套通用的解决方案。
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
迭代器模式提供了一种方法,用于遍历集合对象中的元素,而又不暴露其内部的细节。
外观模式又叫门面模式,它提供了一个统一的(高层)接口,用来访问子系统中的一群接口,使得子系统更容易使用。
单例模式(Singleton Design Pattern)保证一个类只能有一个实例,并提供一个全局访问点。
组合模式可以将对象组合成树形结构来表示“整体-部分”的层次结构,使得客户可以用一致的方式处理个别对象和对象组合。
装饰者模式能够更灵活的,动态的给对象添加其它功能,而不需要修改任何现有的底层代码。
观察者模式(Observer Design Pattern)定义了对象之间的一对多依赖,当对象状态改变的时候,所有依赖者都会自动收到通知。
代理模式为对象提供一个代理,来控制对该对象的访问。代理模式在不改变原始类代码的情况下,通过引入代理类来给原始类附加功能。
工厂模式(Factory Design Pattern)可细分为三种,分别是简单工厂,工厂方法和抽象工厂,它们都是为了更好的创建对象。
状态模式允许对象在内部状态改变时,改变它的行为,对象看起来好像改变了它的类。
命令模式将请求封装为对象,能够支持请求的排队执行、记录日志、撤销等功能。
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。 基本介绍 **意图:**在不破坏封装性的前提下,捕获一个对象的内部状态,并在该
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为
享元模式(Flyweight Pattern)(轻量级)(共享元素)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结