Spring框架 一、什麼是Spring Spring框架是由於軟體開發的複雜性而創建的。Spring使用的是基本的JavaBean來完成以前只可能由EJB完成的事情。然而,Spring的用途不僅僅限於伺服器端的開發。從簡單性、可測試性和松耦合性角度而言,絕大部分Java應用都可以從Spring中受 ...
Spring框架
一、什麼是Spring
Spring框架是由於軟體開發的複雜性而創建的。Spring使用的是基本的JavaBean來完成以前只可能由EJB完成的事情。然而,Spring的用途不僅僅限於伺服器端的開發。從簡單性、可測試性和松耦合性角度而言,絕大部分Java應用都可以從Spring中受益。Spring是一個輕量級控制反轉(IoC)和麵向切麵(AOP)的容器框架。 ◆目的:解決企業應用開發的複雜性 ◆功能:使用基本的JavaBean代替EJB,並提供了更多的企業應用功能 ◆範圍:任何Java應用 ----------------百度百科 二、什麼是IOC 控制反轉(Inversion of Control,英文縮寫為IoC)把創建對象的權利交給框架,是框架的重要特征,並非面向對象編程的專用術語。它包括依賴註入和依賴查找。傳統的業務層,當需要資源時就在該業務層new資源,這樣耦合性(程式之間相互依賴關聯)較高。現在將new的部分交給spring,做到高內聚低耦合。簡而言之:原先是每當調用dao層或service層方法時,由app來new,現在是將new的權利交給spring,要什麼資源從spring中獲取! 三、快速搭建框架環境1.下載框架所需的依賴jar包 spring官網為:http://spring.io/ 下載jar包: http://repo.springsource.org/libs-release-local/org/springframework/spring 2.導入基本jar包
其實基本核心jar有beans;context;core;expression包,其他是依賴log4j日誌。當然spring的jar不止這些,後期慢慢加上。
3.配置log4j配置文件
日誌文件定義在src目錄下
### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.err log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to file mylog.log ### log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=c\:mylog.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### set log levels - for more verbose logging change 'info' to 'debug' ### log4j.rootLogger=info, stdout
4.測試日誌文件是否部署成功
package com.clj.demo1; import org.apache.log4j.Logger; import org.junit.Test; /** * 演示日誌用法 * @author Administrator * */ public class Demo1 { //創建日誌類 private Logger log=Logger.getLogger(Demo1.class); @Test public void run1(){ //可以將log4j.rootLogger屬性中的info改為off則不會再控制台顯示 log.info("執行了"); } }
5.定義一個介面和實現類
介面:
package com.clj.demo2; public interface UserService { public void sayHello(); }
實現類
package com.clj.demo2; public class UserServiceImpl implements UserService{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void init(){ System.out.println("初始化。。"); } public void sayHello() { System.out.println("Hello Spring"+"\t"+name); } public void destory(){ System.out.println("銷毀。。"); } }
6.定義spring專屬的配置文件
定義名為applicationContext.xml,位置為src下,與日誌文件同目錄,導入相對應的約束,並將實現類註入到配置文件中,剛開始入門,使用bean約束
<?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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 使用bean標簽 1.id值唯一(必寫) 2.註意:class為實現類路徑,不是介面(必寫) 3.init-method核心方法執行之前初始化工作(選寫) 4.destroy-method核心方法執行之後初始化工作(選寫)--> <bean id="userService" class="com.clj.demo2.UserServiceImpl" init-method="init" destroy-method="destory"> <property name="name" value="佳先森"></property> </bean>
</beans>
7.測試
public class Demo1 { /** * 原始方式 */ @Test public void run(){ //創建實現類 UserServiceImpl s=new UserServiceImpl(); s.setName("佳先森"); s.sayHello(); } /** * 老的工廠版本BeanFactory * 舊的工廠不會創建配置文件對象 */ @Test public void run2(){ BeanFactory factory=new XmlBeanFactory(new ClassPathResource("applicationContext.xml")); UserService us=(UserService)factory.getBean("userService"); us.sayHello(); } /** * 使用spring框架IOC方式 * 新版本factory創建啟動伺服器會創建配置文件對象,再次調用時無需載入工廠 */ @Test public void run3(){ //創建工廠,載入核心配置文件(ClassPathXmlApplicationContext從src下找) ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); //從工廠中獲取到對象(配置文件中的id值,這裡用了多態) UserService usi=(UserService) ac.getBean("userService"); //調用對象的方法執行 usi.sayHello(); } /** * 演示destroy-method方法 * bean摧毀方法不會自動執行 * 除非scope= singleton或者web容器中會自動調用,但是main函數或測試用例需要手動調用(需要使用ClassPathXmlApplicationContext的close()方法) */ @Test public void run4(){ //創建工廠,載入核心配置文件(ClassPathXmlApplicationContext從src下找) ClassPathXmlApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); //從工廠中獲取到對象(配置文件中的id值,這裡用了多態) UserService usi=(UserService) ac.getBean("userService"); //調用對象的方法執行 usi.sayHello(); //ApplicationContext實現類提供close方法,將工廠關閉就可執行destory-method方法 ac.close(); } }
其中舊工廠與新工廠的區別
* BeanFactory和ApplicationContext的區別
* BeanFactory -- BeanFactory採取延遲載入,第一次getBean時才會初始化Bean
* ApplicationContext -- 在載入applicationContext.xml時候就會創建具體的Bean對象的實例,還提供了一些其他的功能
* 事件傳遞
* Bean自動裝配
* 各種不同應用層的Context實現
總結:這是個最基本的demo,是將實現類配置到了spring配置文件中,每次啟動伺服器時,就會載入配置文件,從而實例化了實現類
四、spring之依賴註入
1、什麼是依賴註入?
Spring 能有效地組織J2EE應用各層的對象。不管是控制層的Action對象,還是業務層的Service對象,還是持久層的DAO對象,都可在Spring的 管理下有機地協調、運行。Spring將各層的對象以松耦合的方式組織在一起,Action對象無須關心Service對象的具體實現,Service對 象無須關心持久層對象的具體實現,各層對象的調用完全面向介面。當系統需要重構時,代碼的改寫量將大大減少。依賴註入讓bean與bean之間以配置文件組織在一起,而不是以硬編碼的方式耦合在一起。理解依賴註入
依賴註入(Dependency Injection)和控制反轉(Inversion of Control)是同一個概念。具體含義是:當某個角色(可能是一個Java實例,調用者)需要另一個角色(另一個Java實例,被調用者)的協助時,在 傳統的程式設計過程中,通常由調用者來創建被調用者的實例。但在Spring里,創建被調用者的工作不再由調用者來完成,因此稱為控制反轉;創建被調用者 實例的工作通常由Spring容器來完成,然後註入調用者,因此也稱為依賴註入。
不管是依賴註入,還是控制反轉,都說明Spring採用動態、靈活的方式來管理各種對象。對象與對象之間的具體實現互相透明。
2. IOC和DI的概念
* IOC -- Inverse of Control,控制反轉,將對象的創建權反轉給Spring!!
* DI -- Dependency Injection,依賴註入,在Spring框架負責創建Bean對象時,動態的將依賴對象註入到Bean組件中!!
3.演示
對於類成員變數,常用的註入方式有兩種
屬性set方法註入和構造方法註入
先演示第一種:屬性set方法註入
1)持久層
package com.clj.demo3; public class CustomerDaoImpl { public void save(){ System.out.println("我是持久層的Dao"); } }
2)業務層
註意:此時是想將持久層註入到業務層,將創建持久層實例權利交給框架,條件是業務層必須提供持久層的成員屬性和set方法
package com.clj.demo3; /** * 依賴註入之將dao 層註入到service層 * @author Administrator * */ public class CustomerServiceImpl{ //提供成員屬相,提供set方法 private CustomerDaoImpl customerDao; public void setCustomerDao(CustomerDaoImpl customerDao) { this.customerDao = customerDao; } public void save(){ System.out.println("我是業務層的service..."); //1.原始方式 //new CustomerDaoImpl().save(); //2.spring 之IOC方式 customerDao.save(); } }
3)配置文件配置
<!-- 演示依賴註入 --> <bean id="customerDao" class="com.clj.demo3.CustomerDaoImpl"/> <bean id="customerService" class="com.clj.demo3.CustomerServiceImpl"> <!-- 將Dao註入到service層 --> <property name="customerDao" ref="customerDao"></property> </bean>
4)測試
/** * spring 依賴註入方式 * 將dao層註入到service層 */ @Test public void run2(){ //創建工廠,載入配置文件,customerService被創建,從而也創建了customerDao ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); CustomerServiceImpl csi=(CustomerServiceImpl) context.getBean("customerService"); csi.save(); }
第二種:構造方法註入
1)pojo類並提供構造方法
package com.clj.demo4; /** * 演示的構造方法的註入方式 * @author Administrator * */ public class Car1 { private String cname; private Double price; public Car1(String cname, Double price) { super(); this.cname = cname; this.price = price; } @Override public String toString() { return "Car1 [cname=" + cname + ", price=" + price + "]"; } }
2)配置文件配置
<!-- 演示構造方法註入方式 -->
<bean id="car1" class="com.clj.demo4.Car1">
<!-- 寫法一<constructor-arg name="cname" value="寶馬"/>
<constructor-arg name="price" value="400000"/> -->
<!--寫法二 -->
<constructor-arg index="0" value="寶馬"/>
<constructor-arg index="1" value="400000"/>
</bean>
3)測試
@Test public void run1(){ ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); Car1 car=(Car1) ac.getBean("car1"); System.out.println(car); }
拓展:構造方法之將一個對象註入到另一個對象中
1)pojo類:目的:將上列中的車註入到人類,使之成為其中一個屬性,則必須在此類中提供車的成員屬性,並提供有參構造方法
package com.clj.demo4; public class Person { private String name; private Car1 car1; public Person(String name, Car1 car1) { super(); this.name = name; this.car1 = car1; } @Override public String toString() { return "Person [name=" + name + ", car1=" + car1 + "]"; } }
2)配置文件
<!-- 構造方法之將一個對象註入到另一個對象-->
<bean id="person" class="com.clj.demo4.Person">
<constructor-arg name="name" value="佳先森"/>
<constructor-arg name="car1" ref="car1"/>
</bean>
4.如何註入集合數組
1)定義pojo類
package com.clj.demo4; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; /** * 演示集合註入的方式 * @author Administrator * */ public class User { private String[] arrs; private List<String> list; private Set<String> sets; private Map<String,String> map; private Properties pro; public void setPro(Properties pro) { this.pro = pro; } public void setSets(Set<String> sets) { this.sets = sets; } public void setMap(Map<String, String> map) { this.map = map; } public void setList(List<String> list) { this.list = list; } public void setArrs(String[] arrs) { this.arrs = arrs; } @Override public String toString() { return "User [arrs=" + Arrays.toString(arrs) + ", list=" + list + ", sets=" + sets + ", map=" + map + ", pro=" + pro + "]"; } }
2)配置文件
<!-- 註入集合 -->
<bean id="user" class="com.clj.demo4.User">
<!-- 數組 -->
<property name="arrs">
<list>
<value>數字1</value>
<value>數字2</value>
<value>數字3</value>
</list>
</property>
<!-- list集合 -->
<property name="list">
<list>
<value>金在中</value>
<value>王傑</value>
</list>
</property>
<!-- set集合 -->
<property name="sets">
<set>
<value>哈哈</value>
<value>呵呵</value>
</set>
</property>
<!-- map集合 -->
<property name="map">
<map>
<entry key="aa" value="rainbow"/>
<entry key="bb" value="hellowvenus"/>
</map>
</property>
<!-- 屬性文件 -->
<property name="pro">
<props>
<prop key="username">root</prop>
<prop key="password">123</prop>
</props>
</property>
</bean>
3)測試
/** * 測試註入集合 */ @Test public void run3(){ ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); User user= (User) ac.getBean("user"); System.out.println(user); }
5.怎麼分模塊開發
在主配置文件加入<import>標簽(假如此時在com.clj.test包下定義了一個配置文件applicationContext2.xml)
<!-- 分模塊開發之引入其他配置文件 -->
<import resource="com/clj/test/applicationContext2.xml"/>
五、詳解Spring框架的IOC之註解方式
1、入門
1).導入jar包
除了先前6個包,玩註解還需一個spring-aop包
2).持久層和實現層(這裡忽略介面)
持久層
package com.clj.demo1; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; /** * UserDaoImpl交給IOC的容器管理 * @author Administrator * */ public class UserDaoImpl implements UserDao{ @Override public void save() { System.out.println("保存客戶。。"); } }
業務層
package com.clj.demo1; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component;
public class UserServiceImpl implements UserService{
@Override public void sayHello() { System.out.println("Hello spring"); } }
3).定義配置文件
此時約束條件需添加context約束,並添加組件掃描
<?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"> <!-- bean definitions here --> <!-- 開啟註解掃面 :base-package指定掃面對 包--> <context:component-scan base-package="com.clj.demo1"/>
</beans>
4)在實現類中添加註解
/** * 組件註解,可以用來標記當前的類 * 類似<bean id="userService" class="com.clj.demo1.UserServiceImpl"> * value表示給該類起個別名 */ @Component(value="userService") public class UserServiceImpl implements UserService{ //省略 }
5)編寫測試
/** * 註解方式 */ @Test public void run2(){ ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); UserService us=(UserService) ac.getBean("userService"); us.sayHello(); }
2.關於bean管理常用屬性
1. @Component:組件.(作用在類上) 最原始的註解,所有需要註解的類都寫這個沒問題,他是通用的 2. Spring中提供@Component的三個衍生註解:(功能目前來講是一致的) * @Controller -- 作用在WEB層 * @Service -- 作用在業務層 * @Repository -- 作用在持久層 * 說明:這三個註解是為了讓標註類本身的用途清晰,Spring在後續版本會對其增強 3. 屬性註入的註解(說明:使用註解註入的方式,可以不用提供set方法) * 如果是註入的普通類型,可以使用value註解 * @Value -- 用於註入普通類型 * 如果註入的是對象類型,使用如下註解 * @Autowired -- 預設按類型進行自動裝配 匹配的是類型,與註入類的類名無關 * 如果想按名稱註入 * @Qualifier -- 強制使用名稱註入 必須與Autowired一起用,指定類名,與註入的類名有關 * @Resource -- 相當於@Autowired和@Qualifier一起使用 * 強調:Java提供的註解 * 屬性使用name屬性
4. Bean的作用範圍註解
* 註解為@Scope(value="prototype"),作用在類上。值如下:
* singleton -- 單例,預設值
* prototype -- 多例
5. Bean的生命周期的配置(瞭解)
* 註解如下:
* @PostConstruct -- 相當於init-method
* @PreDestroy -- 相當於destroy-method
1.演示屬性對象註解
條件:採用掃描的方式將屬性(name)和對象(userDaoImpl)註入到業務層中
1)持久層開啟註解掃描Repository
//@Component(value="userDao")通用類註解 @Repository(value="ud") public class UserDaoImpl implements UserDao{ @Override public void save() { System.out.println("保存客戶。。"); } }
2)業務層針對屬性和對象提供註解
package com.clj.demo1; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** * 組件註解,可以用來標記當前的類 * 類似<bean id="userService" class="com.clj.demo1.UserServiceImpl"> * value表示給該類起個別名 */ //@Scope(value="grototype")多列的(singletype為單列) @Component(value="userService") public class UserServiceImpl implements UserService{ //屬性註解:相當於給name屬性註入指定的字元串,setName方法可以省略不寫 @Value(value="佳先森") private String name; /** * 引用註入方式一:Autowired() * 引用註入方式二:Autowired()+Qualifier * 引用註入方式三:@Resource(name="userDao") java方式,按名稱識別註入 */ //Autowired()按類型自動裝配註入(缺點:因為是按類型匹配,所以不是很準確) @Autowired() @Qualifier(value="ud") //按名稱註入,得與Autowired一起用,兩者一起能指定類 private UserDao userDao; //註意Qualifier中的value是指定UserDaoImpl類名頂上的註解名,也可以指定配置文件中bean的id名 /*public void setName(String name) { this.name = name; }*/ @Override public void sayHello() { System.out.println("Hello spring"+name); userDao.save(); } //@PostConstruct標簽用於action生命周期中初始化的註解 @PostConstruct public void init(){ System.out.println("初始化..."); } }
3)配置文件只需要開啟全部掃描即可
<?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"> <!-- bean definitions here --> <!-- 開啟註解掃面 :base-package指定掃面對 包--> <context:component-scan base-package="com.clj.demo1"/> </beans>
註意:至於集合還是推薦使用配置文件方式
2.Spring框架整合JUnit單元測試
1)添加單元測試所需依賴包spring-test.jar
註意:基於myeclipes自帶Junit環境,但是有時因為版本問題,可能需要比較新的Junit環境,這裡我在網上下了一個教新的 Junit-4.9的jar包,如果myeclipes較新的話無須考慮
2)編寫測試類,添加相對應的註解
@RunWith與@ContextConfiguration(此是用於載入配置文件,因為預設從WebRoot路徑為一級目錄,加上此是認定src為一級目錄)
package com.clj.demo2; import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.clj.demo1.UserService; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class Demo2 { @Resource(name="userService") private UserService userService; @Test public void run1(){ userService.sayHello(); } }
六.spring框架之AOP
1.什麼是AOP
* 在軟體業,AOP為Aspect Oriented Programming的縮寫,意為:面向切麵編程,功能模塊化
* AOP是一種編程範式,隸屬於軟工範疇,指導開發者如何組織程式結構
* AOP最早由AOP聯盟的組織提出的,制定了一套規範.Spring將AOP思想引入到框架中,必須遵守AOP聯盟的規範
* 通過預編譯方式和運行期動態代理實現程式功能的統一維護的一種技術
* AOP是OOP的延續,是軟體開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生範型
* 利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率
AOP採取橫向抽取機制,取代了傳統縱向繼承體系重覆性代碼(性能監視、事務管理、安全檢查、緩存)
2. 為什麼要學習AOP
* 可以在不修改源代碼的前提下,對程式進行增強!!(為固定的方法生成一個代理,在訪問該方法之前,先進入代理,在代理中,可以編寫更多的功能,使之方法的功能更強,使得程式進行增 強)
Aop:面向切麵編程,將一切事模塊化,每個模塊比較獨立,模塊可以共用(相同的),不同的格外自定義。用此替代傳統的面向縱向編程,提高程式的可重用性
3.AOP的實現(實現原理)
Aop的實現包含兩種代理方式<1>實現類介面:採用JDK動態代理<2>未實現類介面:採用CGLIB動態代理
1.實現JDK動態代理
1)定義持久層介面實現類
package com.clj.demo3; public interface UserDao { public void save(); public void update(); }
package com.clj.demo3; public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("保存用戶"); } @Override public void update() { System.out.println("修改用戶"); } }
2)定義JDK動態代理工具類
此工具類是在執行持久層save方法時增加一些功能,在開發中做到在不更改源碼情況下增強某方法
package com.clj.demo3; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 使用JDK的方式生成代理對象(演示AOP原理) * @author Administrator * */ public class MyProxyUtils { public static UserDao getProxy(final UserDao dao){ //使用Proxy類生成代理對象 UserDao proxy=(UserDao)Proxy.newProxyInstance(dao.getClass().getClassLoader() , dao.getClass().getInterfaces(),new InvocationHandler() { //只要代理對象一執行,invoke方法就會執行一次 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //proxy代表當前代理對象 //method當前對象執行的方法 //args封裝的參數 //讓到類的save或者update方法正常執行下去 if("save".equals(method.getName())){ System.out.println("執行了保存"); //開啟事務 } return method.invoke(dao, args); } }); return proxy; } }
3)測試
package com.clj.demo3; import org.junit.Test; public class Demo1 { @Test public void run1(){ //獲取目標對象 UserDao dao=new UserDaoImpl(); dao.save(); dao.update(); System.out.println("==============="); //使用工具類,獲取到代理對象 UserDao proxy=MyProxyUtils.getProxy(dao); //調用代理對象的方法 proxy.save(); proxy.update(); } }
2.實現CGLIB技術
1)定義持久層,此時沒有介面
package com.clj.demo4; public class BookDaoImpl { public void save(){ System.out.println("保存圖書"); } public void update(){ System.out.println("修改圖書"); } }
2)編寫工具類
package com.clj.demo4; import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; /** * Cglib代理方式實現原理 * @author Administrator * */ public class MyCglibUtils { /** * 使用CGLIB方式生成代理對象 * @return */ public static BookDaoImpl getProxy(){ Enhancer enhancer=new Enhancer(); //設置父類 enhancer.setSuperclass(BookDaoImpl.class); //設置回調函數 enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] objs, MethodProxy methodProxy) throws Throwable { if(method.getName().equals("save")){ System.out.println("我保存了"); System.out.println("代理對象執行了"); } return methodProxy.invokeSuper(obj, objs);//是方法執行下去 } }); //生成代理對象 BookDaoImpl proxy=(BookDaoImpl) enhancer.create(); return proxy; } }
3)編寫測試類
package com.clj.demo4; import org.junit.Test; public class Demo1 { @Test public void run1(){ //目標對象 BookDaoImpl dao=new BookDaoImpl(); dao.save(); dao.update(); System.out.println("=========="); BookDaoImpl proxy=MyCglibUtils.getProxy(); proxy.save(); proxy.update(); } }
3、Spring基於AspectJ的AOP的開發(配置文件方式)
1)部署環境,導入相對應的jar包