IOC技術: 控制反轉,也叫(依賴注入) java
控制反轉:Bean的生命週期不受你控制,而是交給Spring容器管理。mysql
Spring框架如何利用IOC ?:
實現了控制反轉,Spring容器能幫咱們實例化對象,可是並無作到DI(依賴注入)。程序員
做用:
(1) 構建Bean
(2) Bean之間有依賴關係的話,能夠自動幫咱們注入
優點:
解耦:低耦合,實現面向接口的編程思想web
動態代理設計模式
原理和靜態代理設計模式沒有本質區別:
被代理類、代理類、被代理和代理類是同一個接口
代理類的建立過程有區別:
(1)靜態代理:
本身編寫代理類,代理類本身實現接口
(2)動態代理:
代理類不須要本身編寫,他Proxy.newProxyinstance(xx)靜態方法
在程序執行過程當中,動態產生代理類
InvocationHandler:裏邊含有被代理類的引用spring
AOP:面向切面的編程sql
代理模式主要的做用:
在業務代碼不之情的狀況下,切入額外的功能。
原理:Spring框架具備IOC的功能,因此咱們能夠利用該功能配置業務Bean 。代理設計模式(動態)
例如: AccountServiceImpl
<bean id="AccountServiceImpl" class="service.AccountServiceImpl"></bean>
而後,Spring框架利用動態代理設計模式建立一個AccountServiceImpl的動態代理對象
而後就能夠在AccountServiceImpl的業務方法的基礎上增長相應的功能。
那Spring把這種技術稱爲AOP面向切面的編程,其實就是在程序員不知情的狀況下在其業務方法上切入額外的功能。
數據庫
使用 XML 配置實現具體的操做:
(1)使用Spring的AOP功能,就須要引入jar pom.xml
(2)本身編寫切面。很相似於InvocationHandler
被代理接口 : 業務接口
被代理類: 實現了被代理口,被代理類也叫業務實現類;
例子:class CalFfabImpl implements ICalFabexpress
代碼示例:
apache
Maven項目編程
pom.xml 添加的插件
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.10</version> </dependency> <!-- https://mvnrepository.com/artifact/aopalliance/aopalliance --> <dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>1.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.10</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency>
添加資源配置文件 beans.xml
<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"> <!-- Spring IOC --> <bean id="calFab" class="day02.aop.CalFabImpl"></bean> <bean id="selfAspectRef" class="day02.aop.SelfAspect"></bean> <!-- Spring Aop 配置切面 --> <aop:config> <!-- 配置切面 --> <aop:aspect ref="selfAspectRef"> <!-- 切點 在CalFabImpl類的任何方法上加通知 --> <aop:pointcut expression="execution(* day02.aop.CalFabImpl.*(..))" id="selfPointcut"/> <!-- 通知 --> <aop:before method="testBefore" pointcut-ref="selfPointcut"/> <aop:after method="testAfter" pointcut-ref="selfPointcut"/> <aop:around method="testAround" pointcut-ref="selfPointcut"/> </aop:aspect> </aop:config> </beans>
新建接口 ICalFab.java
1 /** 2 * 業務接口 3 * @author 張澤 4 */ 5 public interface ICalFab { 6 7 int calFaByLoop(int n); 8 int calFabByRecursion(int n); 9 10 }
新建類實現接口:
/** * 業務實現類:被代理類 * @author 張澤 */ class CalFabImpl implements ICalFab{ @Override public int calFaByLoop(int n) { int n1=1,n2= 1,n3=0; for (int i = 3; i < n; i++) { n3=n1+n2; n1=n2; n2=n3; } return n3; } @Override public int calFabByRecursion(int n) { if(n==1||n==2) return 1; return calFabByRecursion(n-1)+calFabByRecursion(n-2); } }
新建類:SelfAspect.java
import org.aspectj.lang.ProceedingJoinPoint; /** * 自定義功能性切面:利用xml配置實現。 * @author 張澤 * */ public class SelfAspect { //--通知:Before類型的Advice public void testBefore() { System.out.println("before do something..."); } //--通知:after類型的通知 public void testAfter() { System.out.println("after do Something..."); } //-- 通知:Around環繞 通知方法的執行點 public int testAround(ProceedingJoinPoint jp) { int result = 0; try { long start = System.currentTimeMillis(); result = (int)jp.proceed(); //-- 執行業務方法 long end = System.currentTimeMillis(); System.out.println(end-start+"ms"); } catch (Throwable e) { e.printStackTrace(); } return result; } }
新建調用類:Invoker.java
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Invoker類 * 功能切入更加靈活 * @author 張澤 * */ public class Invoker { public static void main(String[] args) { //-- 1. Spring容器 ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml"); //-- 2. 獲取業務類 ICalFab calFab= (ICalFab)ctx.getBean("calFab"); //-- 3. 調用業務方法 System.out.println(calFab.calFaByLoop(40)); System.out.println(calFab.calFabByRecursion(40)); System.out.println(calFab instanceof ICalFab); } }
使用 註解 配置實現具體的操做:
(1) Config類來代替xml的配置
@EnableAspectJAutoProxy //-- 啓用SpringAop的功能
//-- 啓用Spring的IOC功能
@Configuration
@ComponentScan({"package1","package2"})
(2)編寫切面。
代碼示例:
新建接口 ICalFab.java
/** * 業務接口 * @author 張澤 * */ public interface ICalFab { int calFaByLoop(int n); int calFabByRecursion(int n); }
新建實現類 CalFabImpl.java
import org.springframework.stereotype.Component; /** * 業務實現類:被代理類 * @author 張澤 */ @Component //-- Spring IOC class CalFabImpl implements ICalFab{ @Override public int calFaByLoop(int n) { int n1=1,n2= 1,n3=0; for (int i = 3; i < n; i++) { n3=n1+n2; n1=n2; n2=n3; } return n3; } @Override public int calFabByRecursion(int n) { if(n==1||n==2) return 1; return calFabByRecursion(n-1)+calFabByRecursion(n-2); } }
新建配置類 AppConfig.java
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; /** * 配置類 * @author 張澤 * 實現IOC功能 * */ @Configuration @EnableAspectJAutoProxy //-- 啓用SpringAop的功能 @ComponentScan("day.annocation")//-- 包名 public class AppConfig { // @Bean // public ICalFab calFabBean() { // return new CalFabImpl(); // } }
新建類:SelfAspect.java
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * 利用標註自定義切面 * @author 張澤 * */ @Aspect @Component public class SelfAspect { //-- 1. 自定義切點,指定目標方法的位置 @Pointcut("execution(* day02.annocation.CalFabImpl.*(..))") public void selfPointcut() { } //-- 2. 通知 @Before("selfPointcut()") public void testBefore() { System.out.println("before do something..."); } @After("selfPointcut()") public void testAfter() { System.out.println("After do something..."); } @Around("selfPointcut()") public int testAround(ProceedingJoinPoint jp) { int result = 0; try { long start = System.currentTimeMillis(); result = (int)jp.proceed(); //-- 執行業務方法 long end = System.currentTimeMillis(); System.out.println(end-start+"ms"); } catch (Throwable e) { e.printStackTrace(); } return result; } }
新建類:Invoker.java
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Invoker { public static void main(String[] args) { //-- 1.構造Spring容器 ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); //-- 2.獲取Beans ICalFab calFab =(ICalFab)ctx.getBean("calFabImpl");//-- 默認是類名首字母小寫 calFab.calFabByRecursion(40); //-- Web服務器啓動的時候實例化一個Spring容器,在Web服務器關閉的時候關閉Spring容器 //-- Servlet的監聽 //-- 容器關閉 ((AnnotationConfigApplicationContext)ctx).close(); } }
Spring 的測試框架創建在JUnit測試框架基礎上的,它是對JUnit的再次封裝。
使用:
配置文件 pom.xml 引入插件
<!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12-beta-3</version> <scope>test</scope> </dependency> <!-- Spring Test --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-test --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.1.7.RELEASE</version> <scope>test</scope> </dependency>
示例測試工程的代碼:
/** * 業務接口 * @author 張澤 * */ public interface IUserService { void login(); }
import org.springframework.stereotype.Component; /** * 業務實現類 * @author 張澤 * */ @Component public class UserServiceImpl implements IUserService { @Override public void login() { System.out.println("login success"); } }
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; /** * Spring配置 * @author 張澤 * */ @Configuration @ComponentScan("day03") public class AppConfig { @Bean("hello") public String hello() { return "hello"; } }
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * 調用 * @author 張澤 * */ public class Invoker { public static void main(String[] args) { //-- Spring COntainer ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); //-- 2. System.out.println(ctx.getBean("hello")); } }
JUnit測試代碼:
/** * 1. 先利用JUnit作單元測試 * @author 張澤 * */ import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class TestDemo { private ApplicationContext ctx; @Before public void before() { ctx = new AnnotationConfigApplicationContext(AppConfig.class); } @Test public void test() { System.out.println(ctx.getBean("hello")); } }
利用Spring test 框架測試:
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * 2. 利用Spring test 框架 * * @RunWith: 實例化Spring容器 * @ContextConfiguration: 指定Spring容器須要的配置類 * 之後你會不多看到Spring容器了 * */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes= {AppConfig.class}) public class TestSpringDemo { @Autowired private String hi; @Autowired private IUserService userService; @Test public void test() { System.out.println(hi); } @Test public void test1() { userService.login(); } }
該項目的配置文件:pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.uek.course</groupId> <artifactId>spring-app</artifactId> <version>0.0.1</version> <packaging>war</packaging> <!-- 2. 項目屬性配置 --> <properties> <!-- 項目編碼使用UTF-8 --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- 忽略掉web.xml文件 ,由於咱們使用servlet3.0開發web項目 --> <failOnMissingWebXml>false</failOnMissingWebXml> <spring.version>5.1.7.RELEASE</spring.version> </properties> <!-- 3. 配置項目所須要的第三方jar 包 --> <dependencies> <!-- servlet api --> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- MySQL數據庫鏈接池 --> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency> <!-- Druid --> <!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.20</version> </dependency> <!-- 單元測試 --> <!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12-beta-3</version> <scope>test</scope> </dependency> <!-- Spring Test --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-test --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.10</version> </dependency> <!-- https://mvnrepository.com/artifact/aopalliance/aopalliance --> <dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>1.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.10</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> </dependencies> <!-- 配置構建插件 --> <build> <plugins> <plugin> <!-- 編譯插件 --> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <!-- Tomcat 插件 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>8080</port> <path>/airsys</path> <!-- 實現熱部署,不須要每次修改代碼後都從新啓動Tomcat --> <contextReloadable>true</contextReloadable> </configuration> </plugin> </plugins> </build> </project>