學(xué)習(xí)Java的同學(xué)注意了!!!
學(xué)習(xí)進(jìn)程中遇到甚么問題或想獲得學(xué)習(xí)資源的話,歡迎加入Java學(xué)習(xí)交換群,群號(hào)碼:183993990 我們1起學(xué)Java!
代理的實(shí)現(xiàn)分動(dòng)態(tài)代理和靜態(tài)代理,靜態(tài)代理的實(shí)現(xiàn)是對(duì)已生成了的JAVA類進(jìn)行封裝。
動(dòng)態(tài)代理則是在運(yùn)行時(shí)生成了相干代理累,在JAVA中生成動(dòng)態(tài)代理1般有兩種方式。
JDK實(shí)現(xiàn)代理生成,是用類 java.lang.reflect.Proxy, 實(shí)現(xiàn)方式以下
EX:
public class JDKProxy {
public static Object getPoxyObject(final Object c) {
return Proxy.newProxyInstance(c.getClass().getClassLoader(), c.getClass().getInterfaces(),// JDK實(shí)現(xiàn)動(dòng)態(tài)代理,但JDK實(shí)現(xiàn)必須需要接口
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
Object reObj = null;
System.out.print("you say: ");
reObj = method.invoke(c, args);
System.out.println(" [" + Calendar.getInstance().get(Calendar.HOUR) + ":"
+ Calendar.getInstance().get(Calendar.MINUTE) + " "
+ Calendar.getInstance().get(Calendar.SECOND) + "]");
return reObj;
}
});
}
}
測(cè)試代理類方法
public class TestForPoxy {
public static void main(String[] args) {
ServiceTest service = new ServiceTestImpl();
System.out.println(service.getClass().getSimpleName());
ServiceTest poxyService = (ServiceTest) JDKProxy.getPoxyObject(service);
System.out.println(poxyService.getClass().getSuperclass());
poxyService.saySomething("hello,My QQ code is 107966750.");
poxyService.saySomething("what 's your name?");
poxyService.saySomething("only for test,hehe.");
}
}
1, Proxy實(shí)現(xiàn)代理的目標(biāo)類必須有實(shí)現(xiàn)接口
2, 生成出來(lái)的代理類為接口實(shí)現(xiàn)類,和目標(biāo)類不能進(jìn)行轉(zhuǎn)換,只能轉(zhuǎn)為接口實(shí)現(xiàn)類進(jìn)行調(diào)用
明顯特點(diǎn):通過此方法生成出來(lái)的類名叫做 $Proxy0
CGLIB是1個(gè)開源項(xiàng)目,官方網(wǎng)址是:http://cglib.sourceforge.net/,可以去上面下載最新JAR包,
本項(xiàng)目用的是cglib⑶.0.jar
本項(xiàng)目還加入了依賴JAR包asm⑷.0.jar,asm-util⑷.0.jar
實(shí)現(xiàn)方式以下
EX:
public class CGLIBProxy {
public static Object getPoxyObject(Object c) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(c.getClass());
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable {
System.out.print("you say: ");
proxy.invokeSuper(arg0, arg2);
System.out.println(" [" + Calendar.getInstance().get(Calendar.HOUR) + ":"
+ Calendar.getInstance().get(Calendar.MINUTE) + " " + Calendar.getInstance().get(Calendar.SECOND)
+ "]");
return null;
}
});
return enhancer.create();
}
}
測(cè)試代理類方法
public class TestForPoxy {
public static void main(String[] args) {
ServiceTest service = new ServiceTestImpl();
System.out.println(service.getClass().getSimpleName());
// ServiceTest poxyService = (ServiceTest) JDKProxy.getPoxyObject(service);
ServiceTest poxyService = (ServiceTest) CGLIBProxy.getPoxyObject(service);
System.out.println(poxyService.getClass().getSuperclass());
poxyService.saySomething("hello,My QQ code is 107966750.");
poxyService.saySomething("what 's your name?");
poxyService.saySomething("only for test,hehe.");
}
}
1, CGLIB實(shí)現(xiàn)方式是對(duì)代理的目標(biāo)類進(jìn)行繼承
2, 生成出了的代理類可以沒方法,生成出來(lái)的類可以直接轉(zhuǎn)換成目標(biāo)類或目標(biāo)類實(shí)現(xiàn)接口的實(shí)現(xiàn)類,因JAVA向上轉(zhuǎn)換
明顯特點(diǎn):通過輸出看出,看誕生成出的代理類的parent類為代理的目標(biāo)類
在spring中,bean都是由動(dòng)態(tài)代理生成出來(lái)的,那末究竟是用JDK的Proxy類實(shí)現(xiàn)呢,還是用CGLIB方式實(shí)現(xiàn)呢。
AOP Spring需要的依賴JAR包有:
spring-asm⑶.2.0.M1.jar
spring-beans⑶.2.0.M1.jar
spring-context⑶.2.0.M1.jar
spring-core⑶.2.0.M1.jar
spring-expression⑶.2.0.M1.jar
spring-aop⑶.2.0.M1.jar
spring-aspects⑶.2.0.M1.jar
commons\commons-logging⑴.1.1\commons-logging⑴.1.1.jar
aopalliance\aopalliance.jar
lib\aspectjweaver.jar
先簡(jiǎn)單的實(shí)現(xiàn)AOP
配置以下
<?xml version="1.0" encoding="utf⑻"?>
<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⑶.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop⑶.2.xsd">
<bean id="test" class="org.ben.spring.service.Test" />
<bean id="aspectBean" class="org.ben.spring.TestAspect" />
<!-- 對(duì)Test類進(jìn)行AOP攔截 -->
<aop:config>
<aop:aspect id="TestAspect" ref="aspectBean">
<!--配置切面-->
<aop:pointcut id="businessService"
expression="execution(* org.ben.spring.service.Test.say(..))" />
<aop:before pointcut-ref="businessService" method="doBefore" />
<aop:after pointcut-ref="businessService" method="doAfter" />
</aop:aspect>
</aop:config>
</beans>
然落后行運(yùn)行結(jié)果以下,表示AOP攔截成功
AOP測(cè)試類
public class TestBeans {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("test.xml");
Test test=(Test) ctx.getBean("test");
System.out.println(test.getClass().getSimpleName());
test.say();
}
}
輸出:
do something in befor
welcome for test
do something in after
第1種情況, Test不實(shí)現(xiàn)任何接口,代碼以下
public class Test {
public void say() {
System.out.println("welcome for test,My QQ is 107966750");
}
}
在TestBeans中加入打印當(dāng)前對(duì)象的名稱
以下:
ApplicationContext ctx = new ClassPathXmlApplicationContext("test.xml");
Test test=(Test) ctx.getBean("test");
System.out.println(test.getClass().getSimpleName());
test.say();
輸出:
Test$$EnhancerByCGLIB$$4791b36c
super class is class org.ben.spring.service.Test
do something in befor
welcome for test
do something in after
明顯看到用了AOP以后,輸出的是代理類對(duì)象Test$$EnhancerByCGLIB$$bb9b6a7c.而且它的父類是我們的代理目標(biāo)類。說(shuō)明是有CGLIB生成的
第2種情況
XML的配置不變,改變代理目標(biāo)類Test的實(shí)現(xiàn)方法,以下
public class Test implements TestInter{
public void say() {
System.out.println("welcome for test,My QQ is 107966750");
}
}
和原來(lái)不同的是多繼承了1個(gè)接口,接口中定義了say()方法
在TestBeans中加入打印當(dāng)前對(duì)象的名稱
以下:
ApplicationContext ctx = new ClassPathXmlApplicationContext("test.xml");
TestInter test=(TestInter) ctx.getBean("test");
System.out.println(test.getClass().getSimpleName());
System.out.println("super class is "+test.getClass().getSuperclass());
test.say();
輸出:
$Proxy0
super class is class java.lang.reflect.Proxy
do something in befor
welcome for test,My QQ is 107966750
do something in after
Spring AOP中,當(dāng)攔截對(duì)象實(shí)現(xiàn)了接口時(shí),生成方式是用JDK的Proxy類。當(dāng)沒有實(shí)現(xiàn)任何接口時(shí)用的是GCLIB開源項(xiàng)陌生成的攔截類的子類.
附上本文測(cè)試的源碼內(nèi)容 源碼下載
學(xué)習(xí)Java的同學(xué)注意了!!!
學(xué)習(xí)進(jìn)程中遇到甚么問題或想獲得學(xué)習(xí)資源的話,歡迎加入Java學(xué)習(xí)交換群,群號(hào)碼:183993990 我們1起學(xué)Java!