[TOC]java
因爲公司有本身的框架,整個架構跟
Spring
幾乎沾不上邊,在業餘時間對Spring
框架的學習,最近開始學習切面編程**「Spring AOP」
**,而且在博文中記錄一下,以便往後快速上手git
這一章先了解一下什麼是AOP,以及寫一個簡單的例子github
aop叫aspect oriented program,面向切面的編程。那什麼是面向切面編程,切面就是可插可拔,俗一點說就是想要就要,想不要就不要。直接看看下圖理解一下spring
咱們在編程的時候不少重複的代碼如:編程
當項目開發到必定程度的時候,咱們若是忽然要說加上這麼多東西,那多要命啊。那麼這個時候咱們能夠考慮加入AOP了架構
有人問,若是不用spring,那還有其餘框架嗎?那是必須的 筆者瞭解到的能夠作到的有下面幾個app
該例子是從spring官網下拿下來進行測試的,筆者嘗試了能夠成功運行框架
<?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" 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"> <!--支持掃描包--> <context:component-scan base-package="com.carl.spring"/> <!--支持註解--> <context:annotation-config/> <!--其餘配置文件--> <import resource="services.xml"></import> </beans>
spring 入口配置文件eclipse
<?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:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--aop start--> <bean id="createUserProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="com.carl.spring.hello.aop.ISampleCreateUser"/> <!-- Use inner bean, not local reference to target --> <property name="target" ref="sampleCreateUser"> </property> <property name="interceptorNames"> <list> <value>debugInterceptor</value> </list> </property> </bean> <!--aop end--> </beans>
該配置是AOP的一個代理配置,獲取對象的時候,直接獲取
createUserProxy
就能夠獲取target
執行的代理對象,(由於ProxyFactoryBean實現了FactoryBean,能夠直接獲取對應的對象);interceptorNames
就是切面的對象了Advice/Advisor/Interceptor
ide
package com.carl.spring.hello.aop; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.stereotype.Component; /** * @author Carl * @date 2016/9/11 */ @Component("debugInterceptor") public class DebugInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { System.out.println("Before: invocation=[" + methodInvocation + "]"); Object rval = methodInvocation.proceed(); System.out.println("Invocation returned"); return rval; } }
methodInvocation.proceed();
爲執行代理方法,在執行代理方法前和執行方法後,執行了一些系統輸出
package com.carl.spring.hello.aop; /** * @author Carl * @date 2016/9/11 */ public interface ISampleCreateUser { String create(); }
這裏只作一個接口的定義
package com.carl.spring.hello.aop; import org.springframework.stereotype.Service; /** * @author Carl * @date 2016/9/11 */ @Service("sampleCreateUser") public class SampleCreateUserImpl implements ISampleCreateUser { @Override public String create() { System.out.println("invoking SampleCreateUserImpl.create()"); return "return res for SampleCreateUserImpl.create()"; } }
注意,這裏有一個註解
@Service("sampleCreateUser")
,不然在service.xml獲取不了代理對象
package com.carl.spring.hello.bean; import org.junit.Before; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author Carl * @date 2016/8/28 */ public abstract class BaseTest { protected ApplicationContext context; @Before public void setUp() throws Exception { context = new ClassPathXmlApplicationContext(new String[] {"application-context.xml"}); } }
package com.carl.spring.hello.aop; import com.carl.spring.hello.bean.BaseTest; import org.junit.Test; import static org.junit.Assert.*; /** * Created by Administrator on 2016/9/11. */ public class ISampleCreateUserTest extends BaseTest { @Test public void create() throws Exception { ISampleCreateUser createUser = context.getBean("createUserProxy", ISampleCreateUser.class); assertNotNull(createUser); String res = createUser.create(); assertEquals("return res for SampleCreateUserImpl.create()", res); System.out.println(res); } }
Junit的真實測試類
該結果是從控制檯中直接輸出
Before: invocation=[ReflectiveMethodInvocation: public abstract java.lang.String com.carl.spring.hello.aop.ISampleCreateUser.create(); target is of class [com.carl.spring.hello.aop.SampleCreateUserImpl]] invoking SampleCreateUserImpl.create() Invocation returned return res for SampleCreateUserImpl.create()
最終仍是實現了切面,可插拔的東西,可是對象必須交給spring進行代理
methodInvocation.proceed()
前置執行/後置執行/異常時執行/先後都執行
**這上面的內容spring均可以很好的解決,在後面的博文中會記下來