Java SSM4——Spring
Java SSM4——Spring
Spring是一個(gè)輕量級的控制反轉(zhuǎn)(IoC)和面向切面(AOP)的容器(框架)
Spring的優(yōu)勢
- 方便解耦,簡化開發(fā)
- Spring就是一個(gè)容器,可以將所有對象創(chuàng)建和關(guān)系維護(hù)交給Spring管理 什么是耦合度?對象之間的關(guān)系,通常說當(dāng)一個(gè)模塊(對象)更改時(shí)也需要更改其他模塊(對象),這就是耦合,耦合度過高會使代碼的維護(hù)成本增加。要盡量解耦
- AOP編程的支持
- Spring提供面向切面編程,方便實(shí)現(xiàn)程序進(jìn)行權(quán)限攔截,運(yùn)行監(jiān)控等功能
- 聲明式事務(wù)的支持
- 通過配置完成事務(wù)的管理,無需手動編程
- 方便測試,降低JavaEE API的使用
- Spring對Junit4支持,可以使用注解測試
- 方便集成各種優(yōu)秀框架
- 不排除各種優(yōu)秀的開源框架,內(nèi)部提供了對各種優(yōu)秀框架的直接支持
1、IOC
Inverse Of Control:控制反轉(zhuǎn):配置文件(解除硬編碼)+反射(解除編譯器依賴)
- 控制:在java中指的是對象的控制權(quán)限(創(chuàng)建、銷毀)
- 反轉(zhuǎn):指的是對象控制權(quán)由原來 由開發(fā)者在類中手動控制交由Spring管理
2、AOP
Aspect Oriented Programming:面向切面編程:動態(tài)代理(方法增強(qiáng))
3、快速入門
默認(rèn)為maven項(xiàng)目
3.1、導(dǎo)入依賴
<dependencies><!--spring--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.9</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version><scope>test</scope></dependency> </dependencies>3.2、Spring核心配置文件
如無特殊需求,我們默認(rèn)spring核心配置文件名為applicationContent.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="HelloSpring" class="club.winkto.bean.HelloSpring"></bean> </beans>3.3、書寫簡單的類
public class HelloSpring {public void hellospring(){System.out.println("hello spring!");} }3.4、測試
@Test public void test(){ClassPathXmlApplicationContext classPathXmlApplicationContext =new ClassPathXmlApplicationContext("applicationContent.xml");HelloSpring hellospring = classPathXmlApplicationContext.getBean("hellospring", HelloSpring.class);hellospring.hellospring(); }4、Spring API
BeanFactory也可以完成ApplicationContext完成的事情,為什么我們要選擇ApplicationContext?
BeanFactory:在第一次調(diào)用getBean()方法時(shí),創(chuàng)建指定對象的實(shí)例
ApplicationContext:在spring容器啟動時(shí),加載并創(chuàng)建所有對象的實(shí)例
4.1、常用實(shí)現(xiàn)類
- ClassPathXmlApplicationContext 它是從類的根路徑下加載配置文件 推薦使用這種
- FileSystemXmlApplicationContext 它是從磁盤路徑上加載配置文件,配置文件可以在磁盤的任意位置
- AnnotationConfigApplicationContext 當(dāng)使用注解配置容器對象時(shí),需要使用此類來創(chuàng)建 spring 容器,它用來讀取注解
5、Spring IOC
5.1、bean
5.1.1、基礎(chǔ)使用
<bean id="" class=""></bean>- id:Bean實(shí)例在Spring容器中的唯一標(biāo)識
- class:Bean的全限定名
- 默認(rèn)情況下它調(diào)用的是類中的 無參構(gòu)造函數(shù),如果沒有無參構(gòu)造函數(shù)則不能創(chuàng)建成功
5.1.2、scope屬性
<bean id="" class="" scope=""></bean>- singleton:單例(默認(rèn))
- 對象創(chuàng)建:當(dāng)應(yīng)用加載,創(chuàng)建容器時(shí),對象就被創(chuàng)建了
- 對象運(yùn)行:只要容器在,對象一直活著
- 對象銷毀:當(dāng)應(yīng)用卸載,銷毀容器時(shí),對象就被銷毀了
- prototype:多例
- 對象創(chuàng)建:當(dāng)使用對象時(shí),創(chuàng)建新的對象實(shí)例
- 對象運(yùn)行:只要對象在使用中,就一直活著
- 對象銷毀:當(dāng)對象長時(shí)間不用時(shí),被 Java 的垃圾回收器回收了
5.1.3、生命周期的配置
<bean id="" class="包名.類名" init-method="指定class的方法" destroy-method="指定class的方法"></bean>- init-method:指定類中的初始化方法名稱
- destroy-method:指定類中銷毀方法名稱
5.1.4、Bean實(shí)例化的三種方式
5.1.4.1、構(gòu)造器實(shí)例化
spring容器通過bean對應(yīng)的默認(rèn)的構(gòu)造函數(shù)來實(shí)例化bean。
上述即是
5.1.4.2、 靜態(tài)工廠方式實(shí)例化
<bean id="" class="包名.類名" factory-method="指定class的方法" />首先創(chuàng)建一個(gè)靜態(tài)工廠類,在類中定義一個(gè)靜態(tài)方法創(chuàng)建實(shí)例。
靜態(tài)工廠類及靜態(tài)方法:
public class MyUserDaoFactory{//靜態(tài)方法,返回UserDaoImpl的實(shí)例對象public static UserDaoImpl createUserDao{return new UserDaoImpl();} }xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd"> <beans><!-- 將指定對象配置給spring,讓spring創(chuàng)建其實(shí)例 --><bean id="userDao" class="com.ioc.MyUserDaoFactory" factory-method="createUserDao"/> </beans>5.1.4.3、 實(shí)例工廠方式實(shí)例化
<bean id="工廠類id" class="包名.類名"/> <bean id="" factory-bean="工廠類id" factorymethod="工廠類id里的方法"/>該種方式的工廠類中,不再使用靜態(tài)方法創(chuàng)建Bean實(shí)例,而是采用直接創(chuàng)建Bean實(shí)例的方式。同時(shí)在配置文件中,需要實(shí)例化的Bean也不是通過class屬性直接指向其實(shí)例化的類,而是通過factory-bean屬性配置一個(gè)實(shí)例工廠,然后使用factory-method屬性確定使用工廠中哪個(gè)方法。
工廠類方法:
public class MyBeanFactory{public MyBeanFactory(){System.out.println("this is a bean factory");}public UserDaoImpl createUserDao(){return new UserDaoImpl();} }xml配置文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd"> <beans><!-- 配置工廠 --><bean id="myBeanFactory" class="com.ioc.MyBeanFactory"/><!-- 使用factory-bean屬性配置一個(gè)實(shí)例工廠,使用factory-method屬性確定工廠中的哪個(gè)方法 --><bean id="userDao" factory-bean="myBeanFactory" factory-method="createUserDao"/> </beans>主函數(shù)
public class Client {public static void main(String[] args) {// TODO Auto-generated method stub//此處定義xml文件放置的位置為src目錄下的com/xml目錄下String path = "com/xml/bean.xml";ApplicationContext application = new ClassPathXmlApplicationContext(path);UserDaoImpl userDao = (UserDaoImpl) application.getBean("userDao");userDao.sayHello(); //調(diào)用UserDaoImpl類的sayHello方法} }5.1.5、別名
5.1.5.1、alias標(biāo)簽
<alias name="hello" alias="hello1"></alias>5.1.5.2、bean標(biāo)簽name屬性
<bean id="HelloSpring" name="hello2 h2,h3;h4" class="club.winkto.bean.HelloSpring"></bean>可寫多個(gè)別名,分隔符為空格,逗號,分號均可
5.2、依賴注入(DI)
Spring 框架核心 IOC 的具體實(shí)現(xiàn)
5.2.1、構(gòu)造方法
mapper
public interface WinktoMapper {void mapper(); } public class WinktoMapperImpl implements WinktoMapper {public void mapper() {System.out.println("假裝自己有了數(shù)據(jù)庫查詢");} }service
public interface WinktoService {void service(); } public class WinktoServiceImpl implements WinktoService {private int a;private WinktoMapperImpl winktoMapper;private Object[] arrays;private List list;private Map<String,Object> map;private Set set;private Properties properties;public WinktoServiceImpl(int a, WinktoMapperImpl winktoMapper, Object[] arrays, List list, Map<String, Object> map, Set set, Properties properties) {this.a = a;this.winktoMapper = winktoMapper;this.arrays = arrays;this.list = list;this.map = map;this.set = set;this.properties = properties;}public void service() {System.out.println("假裝自己開啟了事務(wù)");winktoMapper.mapper();System.out.println("=================");System.out.println(toString());System.out.println("=================");System.out.println("假裝自己提交了事務(wù)");}@Overridepublic String toString() {return "WinktoServiceImpl{" +"a=" + a +", winktoMapper=" + winktoMapper +", arrays=" + arrays +", list=" + list +", map=" + map +", set=" + set +", properties=" + properties +'}';} }aplicationContent.xml
<bean id="winktoMapper" class="club.winkto.mapper.WinktoMapperImpl"></bean><bean id="winktoService" class="club.winkto.service.WinktoServiceImpl"><!--<constructor-arg index="0" value="12"></constructor-arg>--><!--<constructor-arg index="1" ref="winktoMapper"></constructor-arg>--><!--<constructor-arg index="2">--><!-- <array>--><!-- <value>1</value>--><!-- <ref bean="winktoMapper"></ref>--><!-- </array>--><!--</constructor-arg>--><!--<constructor-arg index="3">--><!-- <list>--><!-- <value>2</value>--><!-- <ref bean="winktoMapper"></ref>--><!-- </list>--><!--</constructor-arg>--><!--<constructor-arg index="4">--><!-- <map>--><!-- <entry key="name" value="zhangsan"></entry>--><!-- <entry key="service" value-ref="winktoMapper"></entry>--><!-- </map>--><!--</constructor-arg>--><!--<constructor-arg index="5">--><!-- <set>--><!-- <value>3</value>--><!-- <ref bean="winktoMapper"></ref>--><!-- </set>--><!--</constructor-arg>--><!--<constructor-arg index="6">--><!-- <props>--><!-- <prop key="name">zhangsan</prop>--><!-- </props>--><!--</constructor-arg>--><constructor-arg name="a" value="12"></constructor-arg><constructor-arg name="winktoMapper" ref="winktoMapper"></constructor-arg><constructor-arg name="arrays"><array><value>1</value><ref bean="winktoMapper"></ref></array></constructor-arg><constructor-arg name="list"><list><value>2</value><ref bean="winktoMapper"></ref></list></constructor-arg><constructor-arg name="map"><map><entry key="name" value="zhangsan"></entry><entry key="service" value-ref="winktoMapper"></entry></map></constructor-arg><constructor-arg name="set"><set><value>3</value><ref bean="winktoMapper"></ref></set></constructor-arg><constructor-arg name="properties"><props><prop key="name">zhangsan</prop></props></constructor-arg></bean> </beans>測試
@Test public void test(){ClassPathXmlApplicationContext classPathXmlApplicationContext =new ClassPathXmlApplicationContext("applicationContent.xml");WinktoService winktoService = classPathXmlApplicationContext.getBean("winktoService", WinktoService.class);winktoService.service(); }5.2.2、set
mapper
public interface WinktoMapper {void mapper(); } public class WinktoMapperImpl implements WinktoMapper {public void mapper() {System.out.println("假裝自己有了數(shù)據(jù)庫查詢");} }service
public interface WinktoService {void service(); } public class WinktoServiceImpl implements WinktoService {private int a;private WinktoMapperImpl winktoMapper;private Object[] arrays;private List list;private Map<String,Object> map;private Set set;private Properties properties;public int getA() {return a;}public void setA(int a) {this.a = a;}public WinktoMapperImpl getWinktoMapper() {return winktoMapper;}public void setWinktoMapper(WinktoMapperImpl winktoMapper) {this.winktoMapper = winktoMapper;}public Object[] getArrayList() {return arrays;}public void setArrayList(Object[] arrays) {this.arrays = arrays;}public List getList() {return list;}public void setList(List list) {this.list = list;}public Map<String, Object> getMap() {return map;}public void setMap(Map<String, Object> map) {this.map = map;}public Set getSet() {return set;}public void setSet(Set set) {this.set = set;}public Properties getProperties() {return properties;}public void setProperties(Properties properties) {this.properties = properties;}public void service() {System.out.println("假裝自己開啟了事務(wù)");winktoMapper.mapper();System.out.println("=================");System.out.println(toString());System.out.println("=================");System.out.println("假裝自己提交了事務(wù)");}@Overridepublic String toString() {return "WinktoServiceImpl{" +"a=" + a +", winktoMapper=" + winktoMapper +", arrays=" + arrays +", list=" + list +", map=" + map +", set=" + set +", properties=" + properties +'}';} }aplicationContent.xml
<bean id="winktoMapper" class="club.winkto.mapper.WinktoMapperImpl"> </bean> <bean id="winktoService" class="club.winkto.service.WinktoServiceImpl"><property name="a" value="12"></property><property name="winktoMapper" ref="winktoMapper"></property><property name="arrayList"><array><value>1</value><ref bean="winktoMapper"></ref></array></property><property name="list"><list><value>2</value><ref bean="winktoMapper"></ref></list></property><property name="map"><map><entry key="name" value="zhangsan"></entry><entry key="service" value-ref="winktoMapper"></entry></map></property><property name="set"><set><value>3</value><ref bean="winktoMapper"></ref></set></property><property name="properties"><props><prop key="name">zhangsan</prop></props></property> </bean>測試
@Test public void test(){ClassPathXmlApplicationContext classPathXmlApplicationContext =new ClassPathXmlApplicationContext("applicationContent.xml");WinktoService winktoService = classPathXmlApplicationContext.getBean("winktoService", WinktoService.class);winktoService.service(); }5.2.3、p命名空間(簡單示范)
導(dǎo)入約束
xmlns:p="http://www.springframework.org/schema/p"mapper
public interface WinktoMapper {void mapper(); } public class WinktoMapperImpl implements WinktoMapper {public void mapper() {System.out.println("假裝自己有了數(shù)據(jù)庫查詢");} }service
public interface WinktoService {void service(); } public class WinktoServiceImpl implements WinktoService {private WinktoMapperImpl winktoMapper;public WinktoMapperImpl getWinktoMapper() {return winktoMapper;}public void setWinktoMapper(WinktoMapperImpl winktoMapper) {this.winktoMapper = winktoMapper;}public void service() {System.out.println("假裝自己開啟了事務(wù)");winktoMapper.mapper();System.out.println("假裝自己提交了事務(wù)");} }aplicationContent.xml
- 對于bean引用用p:xxx-ref
- 否則使用p:xxx
測試
@Test public void test(){ClassPathXmlApplicationContext classPathXmlApplicationContext =new ClassPathXmlApplicationContext("applicationContent.xml");WinktoService winktoService = classPathXmlApplicationContext.getBean("winktoService", WinktoService.class);winktoService.service(); }5.2.4、c命名空間(簡單示范)
導(dǎo)入約束
xmlns:c="http://www.springframework.org/schema/c"mapper
public interface WinktoMapper {void mapper(); } public class WinktoMapperImpl implements WinktoMapper {public void mapper() {System.out.println("假裝自己有了數(shù)據(jù)庫查詢");} }service
public interface WinktoService {void service(); } public class WinktoServiceImpl implements WinktoService {private WinktoMapperImpl winktoMapper;public WinktoMapperImpl getWinktoMapper() {return winktoMapper;}public void setWinktoMapper(WinktoMapperImpl winktoMapper) {this.winktoMapper = winktoMapper;}public void service() {System.out.println("假裝自己開啟了事務(wù)");winktoMapper.mapper();System.out.println("假裝自己提交了事務(wù)");} }aplicationContent.xml
- 對于bean引用用c:xxx-ref
- 否則使用c:xxx
- c命名空間可以額外使用c:_0-ref
測試
@Test public void test(){ClassPathXmlApplicationContext classPathXmlApplicationContext =new ClassPathXmlApplicationContext("applicationContent.xml");WinktoService winktoService = classPathXmlApplicationContext.getBean("winktoService", WinktoService.class);winktoService.service(); }5.3、配置文件模塊化
5.3.1、配置文件并列
ClassPathXmlApplicationContext classPathXmlApplicationContext =new ClassPathXmlApplicationContext("applicationContent.xml","beans.xml");5.3.2、主從配置文件
在applicationContent.xml導(dǎo)入beans.xml
<import resource="beans.xml"/>6、Spring注解開發(fā)(IOC部分)
Spring是輕代碼而重配置的框架,配置比較繁重,影響開發(fā)效率,所以注解開發(fā)是一種趨勢,注解代 替xml配置文件可以簡化配置,提高開發(fā)效率
開啟注解掃描
<!--注解的組件掃描--> <context:component-scan base-package="club.winkto"></context:component-scan>6.1、注冊bean
| @Component | 使用在類上用于實(shí)例化Bean |
| @Controller | 使用在web層類上用于實(shí)例化Bean |
| @Service | 使用在service層類上用于實(shí)例化Bean |
| @Repository | 使用在dao層類上用于實(shí)例化Bean |
6.2、依賴注入
| @Autowired | 使用在字段上用于根據(jù)類型依賴注入(先根據(jù)type,類型不唯一根據(jù)name自動裝配的) |
| @Qualifier | 結(jié)合@Autowired一起使用,根據(jù)名稱進(jìn)行依賴注入 |
| @Resource | 相當(dāng)于@Autowired+@Qualifier,按照名稱進(jìn)行注入(很少用且jdk11在spring核心包不包含此注解) |
| @Value | 注入普通屬性(也可以注入spring配置文件里的其他普通屬性使用${},上面三個(gè)注入引用類型) |
6.3、初始銷毀
| @PostConstruct | 使用在方法上標(biāo)注該方法是Bean的初始化方法 |
| @PreDestroy | 使用在方法上標(biāo)注該方法是Bean的銷毀方法 |
6.4、新注解
| @Configuration | 用于指定當(dāng)前類是一個(gè)Spring 配置類,當(dāng)創(chuàng)建容器時(shí)會從該類上加載注解 |
| @Bean | 使用在方法上,標(biāo)注將該方法的返回值存儲到 Spring 容器中 |
| @PropertySource | 用于加載 properties 文件中的配置 |
| @ComponentScan | 用于指定 Spring 在初始化容器時(shí)要掃描的包 |
| @Import | 用于導(dǎo)入其他配置類 |
6.5、注解快速入門
mapper
public interface WinktoMapper {void mapper(); } @Repository("winktoMapper") public class WinktoMapperImpl implements WinktoMapper {public void mapper() {System.out.println("假裝自己有了數(shù)據(jù)庫查詢");} }service
public interface WinktoService {void service(); } @Service("winktoService") public class WinktoServiceImpl implements WinktoService {@Value("12")private int a;@Autowiredprivate WinktoMapperImpl winktoMapper;public WinktoServiceImpl() {}public WinktoServiceImpl(int a, WinktoMapperImpl winktoMapper) {this.a = a;this.winktoMapper = winktoMapper;}public int getA() {return a;}public void setA(int a) {this.a = a;}public WinktoMapperImpl getWinktoMapper() {return winktoMapper;}public void setWinktoMapper(WinktoMapperImpl winktoMapper) {this.winktoMapper = winktoMapper;}public void service() {System.out.println("假裝自己開啟了事務(wù)");winktoMapper.mapper();System.out.println("=================");System.out.println(toString());System.out.println("=================");System.out.println("假裝自己提交了事務(wù)");}@Overridepublic String toString() {return "WinktoServiceImpl{" +"a=" + a +", winktoMapper=" + winktoMapper +'}';} }aplicationContent.xml
<?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"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><!--注解的組件掃描--><context:component-scan base-package="club.winkto"></context:component-scan> </beans>測試
@Test public void test(){ClassPathXmlApplicationContext classPathXmlApplicationContext =new ClassPathXmlApplicationContext("applicationContent.xml");WinktoService winktoService = classPathXmlApplicationContext.getBean("winktoService", WinktoService.class);winktoService.service(); }6.6、純注解開發(fā)
導(dǎo)入依賴
<dependencies><!--spring--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.9</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version><scope>test</scope></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.6</version></dependency> </dependencies>mapper
public interface WinktoMapper {void mapper(); } @Repository("winktoMapper") public class WinktoMapperImpl implements WinktoMapper {@Value("${name}")private String name;public void mapper() {System.out.println(name);System.out.println("假裝自己有了數(shù)據(jù)庫查詢");} }service
public interface WinktoService {void service(); } @Service("winktoService") public class WinktoServiceImpl implements WinktoService {@Value("12")private int a;@Autowiredprivate WinktoMapperImpl winktoMapper;public WinktoServiceImpl() {}public WinktoServiceImpl(int a, WinktoMapperImpl winktoMapper) {this.a = a;this.winktoMapper = winktoMapper;}public int getA() {return a;}public void setA(int a) {this.a = a;}public WinktoMapperImpl getWinktoMapper() {return winktoMapper;}public void setWinktoMapper(WinktoMapperImpl winktoMapper) {this.winktoMapper = winktoMapper;}public void service() {System.out.println("假裝自己開啟了事務(wù)");winktoMapper.mapper();System.out.println("=================");System.out.println(toString());System.out.println("=================");System.out.println("假裝自己提交了事務(wù)");}@Overridepublic String toString() {return "WinktoServiceImpl{" +"a=" + a +", winktoMapper=" + winktoMapper +'}';} }config
@Configuration @PropertySource("classpath:database.properties") public class WinktoMapperConfig {@Value("${name}")private String name; } @Configuration @ComponentScan("club.winkto") @Import(WinktoMapperConfig.class) public class WinktoConfig {@Beanpublic ObjectMapper objectMapper(){return new ObjectMapper();} }測試
@Test public void test() throws JsonProcessingException {AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(WinktoConfig.class);WinktoService winktoService = annotationConfigApplicationContext.getBean("winktoService", WinktoService.class);ObjectMapper objectMapper = annotationConfigApplicationContext.getBean("objectMapper", ObjectMapper.class);System.out.println(objectMapper.writeValueAsString(winktoService));winktoService.service(); }6.7、Spring整合junit
導(dǎo)入依賴
<dependencies><!--spring--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.9</version></dependency><!--spring-test--><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.3.9</version><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version><scope>test</scope></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.6</version></dependency> </dependencies>修改Test類
@RunWith(SpringJUnit4ClassRunner.class) //@ContextConfiguration(value = {"classpath:applicationContext.xml"}) @ContextConfiguration(classes = {WinktoConfig.class}) public class MyTest {@Autowiredprivate WinktoService winktoService;@Autowiredprivate ObjectMapper objectMapper;@Testpublic void test() throws JsonProcessingException {System.out.println(objectMapper.writeValueAsString(winktoService));winktoService.service();} }7、動態(tài)代理
7.1、JDK動態(tài)代理
基于接口的動態(tài)代理技術(shù):利用攔截器(必須實(shí)現(xiàn)invocationHandler)加上反射機(jī)制生成 一個(gè)代理接口的匿名類,在調(diào)用具體方法前調(diào)用InvokeHandler來處理,從而實(shí)現(xiàn)方法增強(qiáng)
7.2.1、JDK動態(tài)代理實(shí)現(xiàn)
service
public interface CRUD {void select();void insert();void update();void delete(); } @Service public class CRUDService implements CRUD {public void select() {System.out.println("假裝自己執(zhí)行了select");}public void insert() {System.out.println("假裝自己執(zhí)行了insert");}public void update() {System.out.println("假裝自己執(zhí)行了update");}public void delete() {System.out.println("假裝自己執(zhí)行了delete");} }config
@Configuration @ComponentScan("cn.winkto") public class WinktoConfig {@Bean("objectMapper")public ObjectMapper getObjectMapper(){return new ObjectMapper();} }代理
@Component public class JDKProxy {public Object proxy(final CRUDService crudService){return Proxy.newProxyInstance(crudService.getClass().getClassLoader(), crudService.getClass().getInterfaces(), new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("代理前");Object invoke = method.invoke(crudService, args);System.out.println("代理后");return invoke;}});} }測試
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {WinktoConfig.class}) public class MyTest {@Autowiredprivate JDKProxy jdkProxy;@Autowiredprivate CRUDService crudService;@Testpublic void test(){CRUD proxy = (CRUD) jdkProxy.proxy(crudService);proxy.select();} }7.2、CGLIB代理
基于父類的動態(tài)代理技術(shù):動態(tài)生成一個(gè)要代理的子類,子類重寫要代理的類的所有不是 final的方法。在子類中采用方法攔截技術(shù)攔截所有的父類方法的調(diào)用,順勢織入橫切邏輯,對方法進(jìn)行 增強(qiáng)
7.2.1、CGLIB代理的實(shí)現(xiàn)
service
public interface CRUD {void select();void insert();void update();void delete(); } @Service public class CRUDService implements CRUD {public void select() {System.out.println("假裝自己執(zhí)行了select");}public void insert() {System.out.println("假裝自己執(zhí)行了insert");}public void update() {System.out.println("假裝自己執(zhí)行了update");}public void delete() {System.out.println("假裝自己執(zhí)行了delete");} }config
@Configuration @ComponentScan("cn.winkto") public class WinktoConfig {@Bean("objectMapper")public ObjectMapper getObjectMapper(){return new ObjectMapper();} }代理
@Component public class CglibProxy {public Object proxy(final CRUDService crudService){return Enhancer.create(crudService.getClass(), new MethodInterceptor() {public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("代理前");Object invoke = method.invoke(crudService, objects);System.out.println("代理后");return invoke;}});} }測試
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {WinktoConfig.class}) public class MyTest {@Autowiredprivate JDKProxy jdkProxy;@Autowiredprivate CglibProxy cglibProxy;@Autowiredprivate CRUDService crudService;@Testpublic void test1(){CRUD proxy = (CRUD) cglibProxy.proxy(crudService);proxy.select();} }8、Spring AOP
AOP 是 OOP(面向?qū)ο缶幊?#xff09; 的延續(xù),是軟件開發(fā)中的一個(gè)熱點(diǎn),也是Spring框架中的一個(gè)重要內(nèi)容,利用AOP可以對業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時(shí)提高了開發(fā)的效率
- 在程序運(yùn)行期間,在不修改源碼的情況下對方法進(jìn)行功能增強(qiáng)
- 邏輯清晰,開發(fā)核心業(yè)務(wù)的時(shí)候,不必關(guān)注增強(qiáng)業(yè)務(wù)的代碼
- 減少重復(fù)代碼,提高開發(fā)效率,便于后期維護(hù)
8.1、Aop術(shù)語解釋
- Target(目標(biāo)對象):代理的目標(biāo)對象
- Proxy (代理):一個(gè)類被 AOP 織入增強(qiáng)后,就產(chǎn)生一個(gè)結(jié)果代理類
- Joinpoint(連接點(diǎn)):所謂連接點(diǎn)是指那些可以被攔截到的點(diǎn)。在spring中,這些點(diǎn)指的是方法,因?yàn)?spring只支持方法類型的連接點(diǎn)
- Pointcut(切入點(diǎn)):所謂切入點(diǎn)是指我們要對哪些 Joinpoint 進(jìn)行攔截的定義
- Advice(通知/ 增強(qiáng)):所謂通知是指攔截到 Joinpoint 之后所要做的事情就是通知 分類:前置通知、后置通知、異常通知、最終通知、環(huán)繞通知
- Aspect(切面):是切入點(diǎn)和通知(引介)的結(jié)合
- Weaving(織入):是指把增強(qiáng)應(yīng)用到目標(biāo)對象來創(chuàng)建新的代理對象的過程。spring采用動態(tài)代理織 入,而AspectJ采用編譯期織入和類裝載期織入
8.2、Aop快速入門
導(dǎo)入依賴
<dependencies><!--spring--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.9</version></dependency><!--spring-test--><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.3.9</version><scope>test</scope></dependency><!--aop--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.6</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version><scope>test</scope></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.6</version></dependency> </dependencies>service
public interface CRUD {void select();void insert();void update();void delete(); } public class CRUDService implements CRUD {public void select() {System.out.println("假裝自己執(zhí)行了select");}public void insert() {System.out.println("假裝自己執(zhí)行了insert");}public void update() {System.out.println("假裝自己執(zhí)行了update");}public void delete() {System.out.println("假裝自己執(zhí)行了delete");} }aop
public class CRUDAdvice {public void before(){System.out.println("前置通知");}public void afterReturning(){System.out.println("后置通知");}public void afterThrowing(){System.out.println("異常通知");}public void after(){System.out.println("最終通知");}public void around(ProceedingJoinPoint ProceedingJoinPoint){System.out.println("環(huán)繞開始");try {ProceedingJoinPoint.proceed();} catch (Throwable throwable) {throwable.printStackTrace();}System.out.println("環(huán)繞結(jié)束");} }applicationContent.xml
<?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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="crudService" class="cn.winkto.service.CRUDService"></bean><bean id="crudAdvice" class="cn.winkto.aop.CRUDAdvice"></bean><aop:config><aop:aspect ref="crudAdvice"><aop:before method="before" pointcut="execution(* cn.winkto.service.CRUDService.*(..))"></aop:before><aop:after method="afterReturning" pointcut="execution(* cn.winkto.service.CRUDService.*(..))"></aop:after></aop:aspect></aop:config> </beans>測試
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(value = {"classpath:applicationContent.xml"}) public class MyTest {@Autowiredprivate CRUD crud;@Testpublic void test(){crud.select();} }8.3、Aop詳解
8.3.1、切點(diǎn)表達(dá)式
execution([修飾符] 返回值類型 包名.類名.方法名(參數(shù)))- 訪問修飾符可以省略
- 返回值類型、包名、類名、方法名可以使用星號 * 代替,代表任意
- 包名與類名之間一個(gè)點(diǎn) . 代表當(dāng)前包下的類,兩個(gè)點(diǎn) … 表示當(dāng)前包及其子包下的類
- 參數(shù)列表可以使用兩個(gè)點(diǎn) … 表示任意個(gè)數(shù),任意類型的參數(shù)列表
8.3.2、切點(diǎn)表達(dá)式的抽取
<?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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="crudService" class="cn.winkto.service.CRUDService"></bean><bean id="crudAdvice" class="cn.winkto.aop.CRUDAdvice"></bean><aop:config><aop:aspect ref="crudAdvice"><aop:pointcut id="point1" expression="execution(* cn.winkto.service.CRUDService.*(..))"/><aop:before method="before" pointcut-ref="point1"></aop:before><aop:after method="afterReturning" pointcut-ref="point1"></aop:after></aop:aspect></aop:config> </beans> <?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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="crudService" class="cn.winkto.service.CRUDService"></bean><bean id="crudAdvice" class="cn.winkto.aop.CRUDAdvice"></bean><aop:config><aop:pointcut id="point1" expression="execution(* cn.winkto.service.CRUDService.*(..))"/><aop:aspect ref="crudAdvice"><aop:before method="before" pointcut-ref="point1"></aop:before><aop:after method="afterReturning" pointcut-ref="point1"></aop:after></aop:aspect></aop:config> </beans>8.3.3、通知類型
<aop:通知類型 method=“通知類中方法名” pointcut=“切點(diǎn)表達(dá)式"></aop:通知類型>| 前置通知 | <aop:before> | 用于配置前置通知,指定增強(qiáng)的方法在切入點(diǎn)方法之前執(zhí)行 |
| 后置通知 | <aop:afterReturning> | 用于配置后置通知。指定增強(qiáng)的方法在切入點(diǎn)方法之后執(zhí)行 |
| 異常通知 | <aop:afterThrowing> | 用于配置異常通知。指定增強(qiáng)的方法出現(xiàn)異常后執(zhí)行 |
| 最終通知 | <aop:after> | 用于配置最終通知。無論切入點(diǎn)方法執(zhí)行時(shí)是否有異常,都會執(zhí)行 |
| 環(huán)繞通知 | <aop:around> | 用于配置環(huán)繞通知。開發(fā)者可以手動控制增強(qiáng)代碼在什么時(shí)候執(zhí)行 |
后置通知與異常通知互斥,環(huán)繞通知一般獨(dú)立使用
9、Spring注解開發(fā)(AOP部分)
導(dǎo)入依賴
<dependencies><!--spring--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.9</version></dependency><!--spring-test--><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.3.9</version><scope>test</scope></dependency><!--aop--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.6</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version><scope>test</scope></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.6</version></dependency> </dependencies>service
public interface CRUD {void select();void insert();void update();void delete(); } public class CRUDService implements CRUD {public void select() {System.out.println("假裝自己執(zhí)行了select");}public void insert() {System.out.println("假裝自己執(zhí)行了insert");}public void update() {System.out.println("假裝自己執(zhí)行了update");}public void delete() {System.out.println("假裝自己執(zhí)行了delete");} }aop
@Component //標(biāo)注為切面類 @Aspect public class CRUDAdvice {@Pointcut("execution(* cn.winkto.service.CRUDService.*(..))")public void point(){}@Before("point()")public void before(){System.out.println("前置通知");}@AfterReturning("point()")public void afterReturning(){System.out.println("后置通知");}public void afterThrowing(){System.out.println("異常通知");}public void after(){System.out.println("最終通知");}public void around(ProceedingJoinPoint ProceedingJoinPoint){System.out.println("環(huán)繞開始");try {ProceedingJoinPoint.proceed();} catch (Throwable throwable) {throwable.printStackTrace();}System.out.println("環(huán)繞結(jié)束");} }config
@Configuration @ComponentScan("cn.winkto") //開啟自動aop代理 @EnableAspectJAutoProxy public class WinktoConfig {@Bean("objectMapper")public ObjectMapper getObjectMapper(){return new ObjectMapper();} }測試
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {WinktoConfig.class}) public class MyTest {@Autowiredprivate CRUD crud;@Testpublic void test(){crud.select();} }10、Spring事務(wù)
- 編程式事務(wù):直接把事務(wù)的代碼和業(yè)務(wù)代碼耦合到一起,在實(shí)際開發(fā)中不用(下文不進(jìn)行詳細(xì)闡述)
- 聲明式事務(wù):采用配置的方式來實(shí)現(xiàn)的事務(wù)控制,業(yè)務(wù)代碼與事務(wù)代碼實(shí)現(xiàn)解耦合
10.1、聲明式事務(wù)(基于XML,整合mybatis)
實(shí)體類
public class Person {private int pid;private String pname;private String ppassword; }mapper
public interface PersonMapper {List<Person> selectPerson(); } public class PersonMapperImpl implements PersonMapper {private SqlSession sqlSession;public PersonMapperImpl(SqlSession sqlSession) {this.sqlSession = sqlSession;}public List<Person> selectPerson() {return sqlSession.getMapper(PersonMapper.class).selectPerson();} }映射文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.winkto.mapper.PersonMapper"><select id="selectPerson" resultType="Person">select * from person</select> </mapper>數(shù)據(jù)庫配置文件
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone =Asia/Shanghai user=root password=blingbling123.mybatis配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings><typeAliases><package name="cn.winkto.bean"></package></typeAliases><mappers><package name="cn.winkto.mapper"/></mappers> </configuration>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" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"><!--開啟注解掃描--><context:component-scan base-package="cn.winkto" /><context:property-placeholder location="classpath:database.properties"/><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${user}"/><property name="password" value="${password}"/></bean><!--sqlSessionFactory--><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="configLocation" value="mybatis-config.xml" /></bean><!--sqlsession--><bean id="sqlsession" class="org.mybatis.spring.SqlSessionTemplate"><constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" /></bean><bean id="personMapper" class="cn.winkto.mapper.PersonMapperImpl"><constructor-arg name="sqlSession" ref="sqlsession" /></bean><!--事務(wù)管理器--><bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><constructor-arg name="dataSource" ref="dataSource" /></bean><!--通知增強(qiáng)--><tx:advice id="txAdvice" transaction-manager="tx"><tx:attributes><tx:method name="*"/></tx:attributes></tx:advice><!--織入事務(wù)--><aop:config><aop:pointcut id="point" expression="execution(* cn.winkto.mapper.PersonMapperImpl.*(..))" /><aop:advisor advice-ref="txAdvice" pointcut-ref="point" /></aop:config> </beans>測試
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(value = {"classpath:applicationContent.xml"}) public class MyTest {@Autowiredprivate PersonMapper personMapper;@Testpublic void test(){System.out.println(personMapper.selectPerson());} }10.1.1、 事務(wù)參數(shù)的配置詳解
<tx:method name="selectPerson" isolation="REPEATABLE_READ" propagation="REQUIRED" timeout="-1" read-only="false"/>- name:切點(diǎn)方法名稱(可以使用*做匹配,類似于模糊查詢)
- isolation:事務(wù)的隔離級別
- propogation:事務(wù)的傳播行為
- timeout:超時(shí)時(shí)間
- read-only:是否只讀
10.2、聲明式事務(wù)(基于注解,整合mybatis)
實(shí)體類
public class Person {private int pid;private String pname;private String ppassword; }數(shù)據(jù)庫配置文件
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone =Asia/Shanghai user=root password=blingbling123.mapper
public interface PersonMapper {List<Person> selectPerson(); } @Repository("personMapper") public class PersonMapperImpl implements PersonMapper {@Autowiredprivate SqlSessionTemplate sqlSession;public PersonMapperImpl(SqlSessionTemplate sqlSession) {this.sqlSession = sqlSession;}//配置事務(wù)屬性(可放置在類上,k)@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout = -1,readOnly = true)public List<Person> selectPerson() {return sqlSession.getMapper(PersonMapper.class).selectPerson();} }映射文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.winkto.mapper.PersonMapper"><select id="selectPerson" resultType="Person">select * from person</select> </mapper>mybatis配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings><typeAliases><package name="cn.winkto.bean"></package></typeAliases><mappers><package name="cn.winkto.mapper"/></mappers> </configuration>config
@Configuration @EnableAspectJAutoProxy @EnableTransactionManagement @ComponentScan("cn.winkto") @PropertySource("classpath:database.properties")public class WinktoConfig {@Value("${driver}")private String driver;@Value("${url}")private String url;@Value("${user}")private String user;@Value("${password}")private String password;@Beanpublic DataSource dataSource(){DruidDataSource druidDataSource = new DruidDataSource();druidDataSource.setDriverClassName(driver);druidDataSource.setUrl(url);druidDataSource.setUsername(user);druidDataSource.setPassword(password);return druidDataSource;}@Beanpublic SqlSessionFactoryBean sqlSessionFactoryBean(@Autowired DataSource dataSource){SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource);sqlSessionFactoryBean.setConfigLocation(new ClassPathResource("mybatis-config.xml"));return sqlSessionFactoryBean;}@Bean("sqlSession")public SqlSessionTemplate sqlSessionTemplate(@Autowired SqlSessionFactoryBean sqlSessionFactoryBean) throws Exception {return new SqlSessionTemplate(sqlSessionFactoryBean.getObject());}@Beanpublic DataSourceTransactionManager dataSourceTransactionManager(){return new DataSourceTransactionManager(dataSource());} }測試
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {WinktoConfig.class}) public class MyTest {@Autowiredprivate PersonMapper personMapper;@Testpublic void test(){System.out.println(personMapper.selectPerson());} }總結(jié)
以上是生活随笔為你收集整理的Java SSM4——Spring的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: import java.awt.even
- 下一篇: 修改linux远程主机名命令hostna