天天看點

Spring注解開發,用JavaConfig配置spring 靜态代理和動态代理,Spring實作aop使用注解開發使用JavaConfig配置spring代理模式AOP

使用注解開發

  1. 類的注入
@Component		//等價于<bean id="user" class="com.lyc.pojo.User"/> 
				//元件,放在類上,說明這個類被Spring管理了
 <!--指定要掃描的包,包下的注解就會生效-->
    <context:component-scan base-package="com.lyc.pojo"/>
           
  1. 屬性的注入

    放在屬性上方

    @value

    @Value("lyc")
    private String name;
    
    //等價于 <property name>
               
    1. @Component會按照mvc三層架構分層,實質上都是元件的裝配
    • dao @Repository
    • service @Service
    • controller @Controller
@Scope("singleton")    //配置bean的作用域,聲明這個類為單例模式
    					//等價于 bean scope标簽
           

xml配置複雜的東西,注解适用于配置簡單的東西

使用JavaConfig配置spring

不使用xml去配置

Javaconfig注冊類到Spring

@Configuration
public class UserConfig {

    @Bean
    public User getUser(){
        return new User();
    }
}
           

測試類

@Test
    public void test2(){
        ApplicationContext context = new AnnotationConfigApplicationContext(UserConfig.class);
        User user = (User) context.getBean("getUser");

        System.out.println(user.getName());
    }
}
           

代理模式

分類

  • 靜态代理
  • 動态代理

靜态代理

  • 抽象角色:一般使用接口或者抽象類
  • 真實角色:被代理的角色
  • 代理角色:代理真實角色,有一些附屬操作
  • 客戶:真實使用資源的人

例子

接口

public interface Rent {
    public  void rent();
}
           

真實角色

public class Host  implements Rent{

    public void rent() {
        System.out.println("租房成功");
    }
}
           

代理角色

public class Proxy implements Rent{

    private Host host;
    public Proxy() {
    }
    public Proxy(Host host) {
        this.host = host;
    }
    public void rent() {
        host.rent();
    }
}
           

客戶

public class Client {
    public static void main(String[] args) {
        Host host = new Host();
        Proxy proxy = new Proxy(host);
        proxy.rent();		//客戶直接面對的是proxy
    }
}
           

好處

  • 使得真實角色的操作更加純粹,不用去關注一些公共的業務
  • 公共業務交給代理角色
  • 公共業務發生擴充的時候,友善集中管理

靜态代理缺點

  • 一個真實角色會産生一個代理角色,代碼量會上去

動态代理

使用反射動态加載類,減少代碼量

  • 抽象角色:一般使用接口或者抽象類
  • 真實角色:被代理的角色
  • 代理角色:代理真實角色,有一些附屬操作,動态生成代理類
  • 客戶:真實使用資源的人

動态分類

  • 基于接口的動态代理
  • 基于類的動态代理

Proxy:代理

InvocationHandler:産生代理類

萬能工具類

//自動生産動态類
public class ProxyInvocationHandler implements InvocationHandler {


    //被代理的接口
    private Object target;

    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    //生成得到代理類
    public  Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }


    //處理代理執行個體,并傳回結果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        Object result = method.invoke(target, args);
        return result;
    }
    public void seeHouse(){
        System.out.println("看房子");
    }
}
           

通過傳入對象不同,來分别加載對應的類,産生對應的代理類!

一個動态代理類代理一個接口

AOP

面向切面程式設計,通過預編譯方式和運作期動态代理程式功能的統一維護的一種技術

在Spring中AOP

提供聲明式事務;允許使用者自定義切面

  • 橫切關注點:跨越應用程式多個子產品的方法或功能。即是與我們業務邏輯無關的,但是我們需要關注的部分,就是橫切關注點,如日志,安全,緩存,事務等等
  • 切面(Aspect):橫切關注點被子產品化的特殊對象,比如日志類
  • 通知(Adivice):切面必須要完成的工作,他是切面類中的一個方法,比如日志類中的方法
  • 目标(Target):被通知對象。一個接口或一個方法
  • 代理(Proxy):向目标對象應用通知之後建立的對象。比如生成的代理類
  • 切入點(PointCut):切面通知執行的地點的定義,比如invoke方法
  • 連接配接點(JointPoint):與切入點比對的執行點
Spring注解開發,用JavaConfig配置spring 靜态代理和動态代理,Spring實作aop使用注解開發使用JavaConfig配置spring代理模式AOP
Spring注解開發,用JavaConfig配置spring 靜态代理和動态代理,Spring實作aop使用注解開發使用JavaConfig配置spring代理模式AOP

Spring5種類型的通知

Spring注解開發,用JavaConfig配置spring 靜态代理和動态代理,Spring實作aop使用注解開發使用JavaConfig配置spring代理模式AOP

使用Spring原生api接口實作aop

一添加配置

<!--使用原生API接口-->
<!--配置aop:需要導入aop限制-->
<aop:config>
    <!--切入點 expression:表達式,execution(要執行的位置!)-->
    <!--限定符,類名,類下面的方法名,參數-->
    <aop:pointcut id="pointcut" expression="execution(public * com.lyc.service.UserServiceImpl.* (..))"/>

    <!--執行環繞-->
    <aop:advisor advice-ref="log" pointcut="pointcut" />
    <aop:advisor advice-ref="afterLog" pointcut="pointcut" />
</aop:config>
           

Userservice接口

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

接口實作類

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

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

    public void update() {
        System.out.println("修改了一個使用者");
    }

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

前置類型操作

@Component
public class Log implements MethodBeforeAdvice {

    /**
     *      method:要執行的目标對象的方法
     *      args:參數
     *      target:目标對象
     */
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"的"+method.getName());
    }
}
           

後置傳回操作

@Component
public class AfterLog implements AfterReturningAdvice {

    // o:傳回值 objects:參數 o1:目标對象
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println(method.getName()+"傳回結果為"+o);
    }
}
           

測試類

@Test
    public void test2(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        UserService userservice = (UserService) context.getBean("userServiceImpl");  //代理接口,但要獲得接口實作類的bean

        userservice.add();

    }
}
           

使用自定義類去實作aop

配置檔案

<!--方式二:自定義類-->
<aop:config>
    <aop:aspect ref="diyPointCut">
        <aop:pointcut id="pointcut" expression="execution(* com.lyc.service.UserServiceImpl.*(..))"/>
        <aop:before method="before" pointcut-ref="pointcut"/>
        <aop:after method="after" pointcut-ref="pointcut"/>
    </aop:aspect>

</aop:config>
           

自定義類

@Component
public class DiyPointCut {
    public void  before(){
        System.out.println("方法執行前");
    }
    public void  after(){
        System.out.println("方法執行後");
    }
}
           

注解實作AOP

配置檔案

切面類

//使用注解方式實作AOP

@Component
@Aspect
public class AnnotationPointCut {

    @Before("execution(* com.lyc.service.UserServiceImpl.*(..))")		//定義切入點
    public void before(){
        System.out.println("方法執行前");
    }
}
 void  after(){
        System.out.println("方法執行後");
    }
}
           

注解實作AOP

配置檔案

切面類

//使用注解方式實作AOP

@Component
@Aspect
public class AnnotationPointCut {

    @Before("execution(* com.lyc.service.UserServiceImpl.*(..))")		//定義切入點
    public void before(){
        System.out.println("方法執行前");
    }
}