1. 程式人生 > 其它 >Spring框架(四) 註解開發、AOP的使用

Spring框架(四) 註解開發、AOP的使用

註解開發、AOP的使用

匯入配置檔案約束:

<?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">
</beans>

註解開發

Bean的實現

1、 配置掃描哪些包下的註解

<?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">
    <!--指定註解掃描包-->
    <context:component-scan base-package="com.study"/>
    <!--開啟註解的支援-->
    <context:annotation-config></context:annotation-config>
</beans>

2、在指定包下編寫類,增加註解

@Component("user")
// 相當於配置檔案中 <bean id="user" class="當前註解的類"/>
public class User {
    public String name = "張三";
}

3、測試

@Test
public void test(){
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("beans.xml");
User user = applicationContext.getBean("user",User.class);
System.out.println(user.name);

屬性注入

1、可以不用提供set方法,直接在直接名上新增@value("值")

// 相當於配置檔案中 <bean id="user" class="當前註解的類"/>
@Component("user")
public class User {
    @Value("張三")
    // 相當於配置檔案中 <property name="name" value="張三"/>
    public String name;
}

2、如果提供了set方法,在set方法上新增@value("值");

@Component("user")
public class User {

    public String name;

    @Value("張三")
    public void setName(String name) {
        this.name = name;
    }
}

衍生註解

@Component三個衍生註解
為了更好的進行分層,Spring可以使用其它三個註解,功能一樣,目前使用哪一個功能都一樣。
@Controller:web層(控制層)
@Service:service層(服務層)
@Repository:dao層(資料訪問層)

@Component //將這個類標註為Spring的一個元件,放到容器中!
public class Dog {
    public String name = "dog";
}

作用域

@scope

  • singleton:預設的,Spring會採用單例模式建立這個物件。關閉工廠 ,所有的物件都會銷燬。
  • prototype:多例模式。關閉工廠 ,所有的物件不會銷燬。內部的垃圾回收機制會回收
@Controller("user")
@Scope("prototype")
public class User {
    @Value("張三")
    public String name;
}

基於Java類進行配置

@Configuration //代表這是一個配置類
@Import(MyConfig2.class)    //匯入合併其他配置類,類似於配置檔案中的inculde標籤
public class MyConfig {
    @Bean //通過方法註冊一個bean,這裡的返回值就Bean的型別,方法名就是bean的id!
    public Dog dog(){
        return new Dog();
    }
}

AOP

AOP(Aspect Oriented Programming)意為:面向切面程式設計,通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術。

通知型別 連線點 實現介面
前置通知 在方法執行前執行 org.spirngframework.aop.MethodBeforeAdvice
後置通知 在方法執行後執行 org.springframework.aop.AfterReturningAdvice
環繞通知 在方法執行前後都執行 org.aopalliance.intercept.MethodInterceptor
異常丟擲通知 在方法丟擲異常後執行 org.springframework.aop.ThrowsAdvice
引介通知 在目標類中新增一些新的方法和屬性 org.springframework.aop.IntroductionInterceptor

使用Spring實現Aop

匯入依賴

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>

第一種實現方式:

1、編寫介面

package com.sutdy.service;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void select();
}

2、編寫介面實現類

package com.study.service;

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加了一個使用者");
    }

    @Override
    public void delete() {
        System.out.println("刪除了一個使用者");
    }

    @Override
    public void update() {
        System.out.println("更新了一個使用者");
    }

    @Override
    public void select() {
        System.out.println("查詢了一個使用者");
    }
}

3、編寫增強類

前置增強:

package com.study.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;
//方法執行前執行該類
public class BeforeLog implements MethodBeforeAdvice {
    //method:要執行的目標方法
    //objects:引數
    //o:目標物件
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println(o.getClass().getName()+"的"+method.getName()+"被執行了");
    }
}

後置增強:

package com.study.log;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;

//方法執行後執行該類
public class AfterLog implements AfterReturningAdvice {
    //returnValue 返回值
    //method被呼叫的方法
    //args 被呼叫的方法的物件的引數
    //target 被呼叫的目標物件
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("執行了"+method.getName()+"方法,返回結果為:"+returnValue);
    }
}

4、編寫配置檔案:

<?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
       http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="userService" class="com.study.service.UserServiceImpl"/>
    <bean id="beforeLog" class="com.study.log.BeforeLog"/>
    <bean id="afterLog" class="com.study.log.AfterLog"/>
    <!--aop的實現方式一-->
    <!--配置aop-->
    <aop:config>
        <!--切入點      execution:要執行的位置:修飾符 返回值 方法名 引數-->
        <aop:pointcut id="pointcut" expression="execution(* com.study.service.UserServiceImpl.*(..))"/>
        <!--執行環繞曾加-->
        <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>
    <aop:aspectj-autoproxy/>
</beans>

5、編寫測試程式碼:

import com.study.service.UserService;
import com.study.service.UserServiceImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationConText.xml");
        UserService userService = context.getBean("userService", UserService.class);
        userService.select();
    }
}

執行結果:

第二種實現方式

自定義類來實現Aop

1、編寫一個切入類

package com.study.diy;

public class AnnotationPointCut {
    @Before("execution(* com.kuang.service.*.*(..))")
    public void before(){
        System.out.println("=========方法執行前=======");
    }
    @After("execution(* com.kuang.service.*.*(..))")
    public void after(){
        System.out.println("=========方法執行後=======");
    }

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
       http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="userService" class="com.study.service.UserServiceImpl"/>
    <bean id="beforeLog" class="com.study.log.BeforeLog"/>
    <bean id="afterLog" class="com.study.log.AfterLog"/>

    <!--aop的實現方式二-->
    <bean id="diy" class="com.study.diy.DiyPointcut"/>
    <aop:config>
        <!--自定義切面 ref:要引用的類-->
        <aop:aspect ref="diy">
            <!--切入點-->
            <aop:pointcut id="point" expression="execution(* com.study.service.UserServiceImpl.*(..))"/>
            <!--通知-->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
    <aop:aspectj-autoproxy/>
</beans>

3.測試

第三種實現方式

使用註解實現

1、編寫一個註解實現的增強類

package com.study.diy;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

//使用註解方式實現aop
@Aspect //標註這個類是一個切面
public class AnnotationPointCut {

    @Before("execution(* com.kuang.service.*.*(..))")
    public void before(){
        System.out.println("=========方法執行前=======");
    }

    @After("execution(* com.kuang.service.*.*(..))")
    public void after(){
        System.out.println("=========方法執行後=======");
    }

    //在環繞增強中,我們可以給定一個引數,代表我們要獲取的切入點
    @Around("execution(* com.kuang.service.*.*(..))")
    public void around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("環繞前");

        //Signature signature = point.getSignature();//獲得簽名(類的資訊)
        //System.out.println("signature"+signature);
        //執行方法
        Object proceed = point.proceed();
        System.out.println("環繞後");
        //System.out.println(proceed);
    }
}

2、在Spring配置檔案中,註冊bean,並增加支援註解的配置

<!--第三種方式:註解實現-->
<bean id="annotationPointcut" class="com.study.config.AnnotationPointcut"/>
<aop:aspectj-autoproxy/>

3、測試