Heim  >  Artikel  >  Java  >  Code-Sharing zweier Spring AOP-Implementierungsmethoden

Code-Sharing zweier Spring AOP-Implementierungsmethoden

零到壹度
零到壹度Original
2018-04-03 15:16:412055Durchsuche

In diesem Artikel wird hauptsächlich die Codefreigabe zweier Spring AOP-Implementierungsmethoden vorgestellt. Der Herausgeber findet ihn recht gut, daher werde ich ihn jetzt mit Ihnen teilen und als Referenz verwenden. Folgen wir dem Editor, um einen Blick darauf zu werfen

1. AOP-Programmierung manuell implementieren (Agentenmodus)

AOP ist aspektorientierte Programmierung und ihre Hauptfunktion besteht darin, „Geschäftscode“ zu implementieren " und zusätzliche „Bedenkencode“-Trennung des Geschäftscodes. Bei einer Methode wird der Kerngeschäftscode freigegeben, die anderen werden als Bedenkencodes bezeichnet. Zum Beispiel das Speichern von Daten in der Datenbank:

// 保存一个用户
public void add(User user) { 
        Session session = null; 
        Transaction trans = null; 
        try { 
            session = HibernateSessionFactoryUtils.getSession();   // 【关注点代码】
            trans = session.beginTransaction();    // 【关注点代码】
             
            session.save(user);     // 核心业务代码
             
            trans.commit();     //…【关注点代码】

        } catch (Exception e) {     
            e.printStackTrace(); 
            if(trans != null){ 
                trans.rollback();   //..【关注点代码】

            } 
        } finally{ 
            HibernateSessionFactoryUtils.closeSession(session);   ////..【关注点代码】

        } 
   }

Wenn im obigen Code mehrere Methoden vorhanden sind, müssen Sie mehrere wiederholte Fokuscodes schreiben. Wenn dies nicht gut ist, können Sie die häufig wiederholten Codes extrahieren und sie dann nur in die Methode im Code einfügen. Schreiben Sie den Kerngeschäftscode. Wenn Sie diese Methode ausführen, wird der extrahierte Fokuscode automatisch ausgeführt. Um diesen Effekt zu erzielen, verwenden Sie am besten den Proxy-Modus. Tatsächlich verwendet die AOP-Programmierung hauptsächlich den Proxy-Modus, um den Kern zu implementieren Code und Fokuscode sind getrennt.

Die manuelle Implementierung von AOP ist die gleiche wie die vorherige Proxy-Modus-Implementierung, daher wird sie nicht mehr veröffentlicht.

2

AOP: Aspect Object Programming

Die Funktion besteht darin, Anliegen und Geschäft ohne Code zu trennen

Bedenken:Doppelte Codes werden Bedenken genannt.
Aspekt:Die durch die Bedenken gebildeten Klassen werden Aspekte (Klassen) genannt.Aspektorientierte Programmierung bezieht sich auf das Extrahieren wiederholter Codes für viele Funktionen und das anschließende Hinzufügen zu Geschäftsmethoden zur Laufzeit. Dynamisches Implantieren von „Aspektklassencode“

Einstiegspunkt: Führen Sie die Zielobjektmethode aus und implantieren Sie den Aspektcode dynamisch. Sie können angeben, welche Klassen über die Einstiegspunktausdrucksmethode abgefangen werden sollen, und den Aspektklassencode zur Laufzeit in die angegebene Klasse einbetten

2.1. Implementierung der Annotationsmethode

Implementierungsschritte:


1. Einführung des AOP-bezogenen JAR-Pakets, insgesamt vier

  • spring-aop-3.2.5.RELEASE.jar

  • aopalliance.jar

  • aspectjweaver.jar

  • aspectjrt.jar

Hinweis: Bei Verwendung der JAR-Datei in der Spring 2.5-Version kann es zu Problemen bei der Verwendung von jdk1.7 kommen. Sie müssen die Aspectj-Komponente aktualisieren , das heißt, verwenden Sie die in der Aspectj-1.8.2-Version bereitgestellte JAR-Datei

2.bean.xml中引入aop名称空间


xmlns:aop="http://www.springframework.org/schema/aop"

3.开始aop注解扫描


    <!-- 开启注解扫描 -->
    <context:component-scan base-package="e_aop_anno"></context:component-scan>
    
        <!-- 开启aop注解方式 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

4.使用注解来实现

  • @Aspect:指定当前类为切面类.

  • @Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))") :指定切入点表达式

  • @Before("pointCut_()"): 前置通知:在目标方法之前执行

  • @After("pointCut_()"):后置通知:目标方法之后执行(如果拦截到,则始终执行)

  • @AfterReturning("pointCut_()"):返回后通知:执行方法结束后执行(异常不执行),@after()之后执行.

  • @AfterThrowing("pointCut_()"):异常通知:出现异常时候执行

  • @Around("pointCut_()"):环绕通知:环绕目标方法执行

代码示例:
目标对象分两个,一个是实现接口IUserDao的UserDao对象和一个没有实现接口的OrderDao对象.然后是抽取出来的切面类Aop,Spring的配置文件bean.xml,以及测试类App

接口IUserDao.java



// 接口
public interface IUserDao {   
    void save();
}

实现接口的:UserDao.java


/** 
* 目标对象 
*/
@Component   // 加入容器
public class UserDao implements IUserDao{    
        
        @Override
        public void save() {
           System.out.println("-----核心业务:保存!!!------");
    }
}

不实现任何接口的OrderDao.java


/** 
* 目标对象 
*/
@Component   // 加入容器
@Scope("prototype")
public class OrderDao{  

  public void save() {
        System.out.println("-----核心业务:保存!!!------");
    }
}

Spring的配置文件bean.xml





    
    

    
    

抽取出来的切面对象Aop.java


@Component
@Aspect  // 指定当前类为切面类
public class Aop {  

  // 指定切入点表单式: 拦截哪些方法; 即为哪些类生成代理对象

    @Pointcut("execution(* e_aop_anno.*.*(..))")
    //    @Pointcut("execution(* e_aop_anno.UserDao.save(..))")//只拦截UserDao中的save()方法
    public void pointCut_(){
    }  
    
      // 前置通知 : 在执行目标方法之前执行
    @Before("pointCut_()")    public void begin(){
        System.out.println("开始事务/异常");
    }  
    
      // 后置/最终通知:在执行目标方法之后执行  【无论是否出现异常最终都会执行】
    @After("pointCut_()")    public void after(){
        System.out.println("提交事务/关闭");
    }  
    
      // 返回后通知: 在调用目标方法结束后执行 【出现异常不执行】
    @AfterReturning("pointCut_()")    public void afterReturning() {
        System.out.println("afterReturning()");
    }    // 异常通知: 当目标方法执行异常时候执行此关注点代码
    @AfterThrowing("pointCut_()")    
    public void afterThrowing(){
        System.out.println("afterThrowing()");
    }  
    
      // 环绕通知:环绕目标方式执行
    @Around("pointCut_()")    
    public void around(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("环绕前....");
        pjp.proceed();  // 执行目标方法
        System.out.println("环绕后....");
    }

}

测试类App.java


public class App {

    ApplicationContext ac =       
         new ClassPathXmlApplicationContext("e_aop_anno/bean.xml");   
   // 目标对象有实现接口,spring会自动选择“JDK代理”,UserDao是实现了接口
    @Test
    public void testApp() {
        IUserDao userDao = (IUserDao) ac.getBean("userDao");
        System.out.println(userDao.getClass());//$Proxy001
        userDao.save();
    }    // 目标对象没有实现接口, spring会用“cglib代理”,OrderDao没有实现接口
    @Test
    public void testCglib() {
        OrderDao orderDao = (OrderDao) ac.getBean("orderDao");
        System.out.println(orderDao.getClass());
        orderDao.save();
    }    @Test
    public void testGetObj() throws Exception {
        OrderDao orderDao1 = (OrderDao) ac.getBean("orderDao");
        OrderDao orderDao2 = (OrderDao) ac.getBean("orderDao");

        System.out.println(orderDao1);//e_aop_anno.OrderDao@5b295b
        System.out.println(orderDao2);//e_aop_anno.OrderDao@1e5f737
         System.out.println(orderDao1==orderDao2);//false

    }
}

测试结果:
testApp()和testCglib()的测试结果为:


//测试输出环绕前....
开始事务/异常
-----核心业务:保存!!!------
环绕后....
提交事务/关闭afterReturning()

2.2.XML配置方式实现

使用XML配置方法来实现AOP编程的步骤:
1.引入jar文件
同注解实现AOP中的四个一样
2.引入aop名称空间
同注解实现AOP中
3.AOP配置
配置主要有两部分组成,一个是各种实例对象的创建,一个是aop的配置(拦截哪些方法/拦截到方法后应用通知代码)

代码示例:
同注解方式中的代码是差不多的,两个对象,分别是实现了接口的UserDao和没有实现任何接口的OrderDao.这个两个类跟上面是一样的,没有做改变,改变是在AOP切面类中以及bean.xml的配置中.测试类也没有做改变
UserDao.java和OrderDoa.java不在显示.
切面类aop.java代码:


// 切面类public class Aop {    public void begin(){
        System.out.println("开始事务/异常");
    }    public void after(){
        System.out.println("提交事务/关闭");
    }    public void afterReturning() {
        System.out.println("afterReturning()");
    }    public void afterThrowing(){
        System.out.println("afterThrowing()");
    }    public void around(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("环绕前....");
        pjp.proceed();  // 执行目标方法
        System.out.println("环绕后....");
    }

}

注意没有注解了.
配置文件bean.xml





    
    
    

    
    

    
    
        
        
        
        
            
            
            
            
            
            
            
            
            
            

        
    

测试类:app.java


public class App {

    ApplicationContext ac =            new ClassPathXmlApplicationContext("f_aop_xml/bean.xml");    // 目标对象有实现接口,spring会自动选择“JDK代理”
    @Test
    public void testApp() {
        IUserDao userDao = (IUserDao) ac.getBean("userDao");
        System.out.println(userDao.getClass());//$Proxy001
        userDao.save();
    }    // 目标对象没有实现接口, spring会用“cglib代理”
    @Test
    public void testCglib() {
        OrderDao orderDao = (OrderDao) ac.getBean("orderDao");
        System.out.println(orderDao.getClass());
        orderDao.save();
    }
}

2.3.切入点表示式

切入点表达式:可以对指定的方法进行拦截,从而给指定的方法所在的类生成代理对象.

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throes-pattern?)


从语法来看,只有返回类型和方法是必须要写的.返回类型一般用表示,写方法的时候可以通过匹配各种包或者类或者方法.

表示式使用示例:




    
    
    

    
    

    
    

        
        

        
        

        
        

        
        

        
        

        
        

        
        
        
        
        
        

        
        
        

        
        
            
            
        
    

Das obige ist der detaillierte Inhalt vonCode-Sharing zweier Spring AOP-Implementierungsmethoden. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn