之前分享過hibernate架構, 這次分享一下關于spring架構的一些内容,都是自我了解的一些内容,僅供參考哦。
首先
介紹一下spring架構:
Spring是一個開源架構,是一個一站式架構
Spring是一個容器,你給他安裝什麼,他就擁有了什麼功能
Struts2他就是一個web層,給他安裝hibernate他就是一個dao層的架構。Service也可以使用spring架構來管理。
Spring springMVC springBoot都是web層的架構
JbdcTemplate spring中也提供了dao層的架構
spring核心思想的介紹:
Ioc (控制反轉)
Di (依賴注入) (技術點)
Aop (面向切面) 事務的管理
簡單的對spring有一些了解之後,就是如何對spring的環境搭建:
Spring環境搭建:
- 導包(需要導入三個依賴:)
<dependencies> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.0.2.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>5.0.2.RELEASE</version> </dependency> </dependencies>
- 然後再準備一個類
- 書寫配置檔案(applicationContext.xml) 引入限制 配置實體類,在spring容器中
- 書寫測試代碼
public class Demo { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User) ac.getBean("user"); System.out.println(user); }
spring核心配置檔案的詳解:
1. 名字和位置
配置檔案名字沒有要求,
位置:maven 放在resource中
2. bean 屬性的配置
功能:配置類 用來建立對象
Class
Name
建立對象的方式:
a) 通過無參的構造函數來建立(預設)
b)通過靜态工廠來執行個體化對象
提供靜态工廠 類中提供一個靜态方法,傳回一個實體對象
public class UserFactory {
public static User createUser(){
return new User();
}
配置檔案:
<bean name="userFactory" class="com.hd.create.UserFactory" factory-method="createUser"></bean>
測試類:
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) ac.getBean("userFactory");
System.out.println(user);
}
c) 通過執行個體化工廠建立對象
準備一個工廠 提供建立對象的方法 public
配置檔案中,既要配置要建立的對象,也要配置工廠
在對象的建立時要指定是哪個工廠中的方法

spring屬性注入:
1. set方法注入(重點)
基礎類型 8大基礎類型和string value注入
<bean name="car" class="com.hd.injection.Car">
<property name="name" value="加長林肯"></property>
<property name="color" value="黑色"></property>
</bean>
引用類型 對象 ref注入
<bean name="user" class="com.hd.test.User">
<property name="name" value="郭婷婷"></property>
<property name="address" value="河南"></property>
<property name="userId" value="0123"></property>
<property name="car" ref="car"></property>
</bean>
2. 構造函數的注入
建立對象用的是制定構造函數建立(按照順序進行注入)
name (構造函數中參數的名字) value(屬性的值) index(該參數的位置) type(該參數的類型)
<constructor-arg name="age" value="12" index="0" type="java.lang.Integer"></constructor-arg>
3. p空間的注入
導入限制
這種方式雖然簡單,但是不被業界認可
4. spel 注入
<bean name="teacher1" class="com.hd.injection.TeacherP">
<property name="name" value="#{teacher.name}"></property>
</bean>
适用于已經在spring容器中有一個對象,重新建立一個對象要用到原來對象中的内容
複雜屬性的注入:
數組屬性注入:
數組屬性注入
<bean name="order" class="com.hd.complexInjection.Order">
<property name="productIds">
<array>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
</array>
</property>
集合:
list Map
<property name="list">
<list>
<value>list集合</value>
<ref bean="car"></ref>
</list>
</property>
<property name="map">
<map>
<entry key="id" value="1123"></entry>
<entry key="car" value-ref="car"></entry>
</map>
</property>
Properties
<property name="properties">
<props>
<prop key="url">jdbc:mysql:localhost:3306</prop>
</props>
</property>
</bean>
注解方式:
1. 開啟注解 制定掃描的包
<context:component-scan base-package="com.hd"></context:component-scan>
2. 使用注解管理對象
@Component //以下三合一注解
@Repository //dao層注解
@Service
@Controller //外部層注解
四種注解,沒有本質差別,隻是為了區分web項目的結構
如果想給對象起個名字在上面小括号中寫入名字即可,如果不寫預設與類型保持一緻(首字母小寫)
3. 對象的範圍
@Scope(scopeName = "prototype")
在類上面進行書寫
4. 在建立對象後和銷毀對象前調用的方法
@PostConstruct
public void init(){
System.out.println("建立對象後調用");
}
@PreDestroy
public void destroy(){
System.out.println("銷毀對象前調用");
}
5. 依賴管理
普通屬性
在屬性或者set方法上面注解
@Value("張三")//在屬性上面注解, set方法可以省略
private String name;
private Integer age;
或者
@Value("21")
public void setAge(Integer age) {
this.age = age;
}
引出類型:
如果該對象在spring中隻有一個
@Autowired
private Car car;
如果有多個還想使用自動裝配,就必須指定
@Autowired
@Qualifier("car2")
private Car car;
如果是多個寫兩個比較麻煩,提供一個新的
@Resource(name = "car2")
private Car car;
Spring結合Junit測試:
導包
Maven項目依賴
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
<scope>test</scope>
</dependency>
Spring AOP:
Aop
面向切面程式設計
Spring aop的原理
代理技術:spring aop用到了java中代理技術,給目标對象生成一個代理對象,生成的目标對象會擁有目标對象的所有方法,隻要在調用目标對象方法前執行代理對象代碼即可。
Spring 實作代理有兩種方式:
- 動态代理(優先考慮): 該目标對象必須實作接口,才能生成代理對象
- Cglib 代理: 不用實作接口,第三方代理技術,實作代理技術原理是使用繼承,要求目标對象不能使用final修飾。
手動實作代理動态代理:
加強service 開啟事務 送出事務
- 準備一個service接口
- 實作service接口
- 建立service的代理對象工廠
Spring 實作代理有兩種方式:
1. 動态代理(優先考慮): 該目标對象必須實作接口,才能生成代理對象
2. Cglib 代理: 不用實作接口,第三方代理技術,實作代理技術原理是使用繼承,要求目标對象不能使用final修飾。
手動實作代理動态代理:
加強service 開啟事務 送出事務
- 準備一個service接口
- 實作service接口
- 建立service的代理對象工廠
public class UserServiceProxyFactory implements InvocationHandler{
private UserService userService;
public UserServiceProxyFactory(UserService userService) {
this.userService = userService;
}
public UserService getUserServiceProxy() {
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(),
UserServiceImpl.class.getInterfaces(), this);
return userServiceProxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("開啟事務");
Object invoke = null;
try{
invoke= method.invoke(userService,args);
System.out.println("送出事務");
}catch (Exception e) {
e.printStackTrace();
System.out.println("復原事務");
}
return invoke;
}
}
cgilb實作代理方法:
- 準備一個類
- 建立生成代理對象的類
public class UserServiceProxyFactory1 implements MethodInterceptor{
public UserService getUserServiceProxy(){
//cglib 提供的api 用來建立代理對象
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserServiceImpl.class);
enhancer.setCallback(this);
UserService o = (UserService) enhancer.create();
return o;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("開啟事務");
Object invoke = methodProxy.invokeSuper(o, objects);
System.out.println("送出事務");
return invoke;
}
SpringAop:
7個專業名詞:
連接配接點 joinPoint 被代理對象擁有所有可以加強的方法
切入點 pointCut 已經被加強的方法
通知 adivce 加強的代碼
目标對象 target 被代理的對象
織入 weaving 将通知應用到目标對象的連接配接點
代理 proxy 生成目标對象的代理對象
切面 aspect 通知+切點
1. 導包(aspect)
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.12</version>
</dependency>
2. 準備一個通知
3. 配置切點和切面
<context:component-scan base-package="com.hd"></context:component-scan>
<bean name="myAdvice" class="com.hd.springAop.MyAdvice"></bean>
<aop:config>
<aop:pointcut id="pt" expression="execution( * com.hd.springAop.*ServiceImpl.*(..) )"></aop:pointcut>
<aop:aspect ref="myAdvice">
<aop:before method="before" pointcut-ref="pt"></aop:before>
<aop:after method="after" pointcut-ref="pt"></aop:after>
<aop:after-returning method="afterReturning" pointcut-ref="pt"></aop:after-returning>
<aop:after-throwing method="afterThrowing" pointcut-ref="pt"></aop:after-throwing>
</aop:aspect>
</aop:config>
- 開啟注解模式
- 在通知中使用注解配置
@Before("MyAdvice.pt()")
public void before(){
System.out.println("注解模式---方法前使用");
}
@After("MyAdvice.pt()")
public void after(){
System.out.println("有異常也正常調用");
}
Spring整合JDBC
Spring是一個容器
Dao層 hibernate mybatis jdbcTemplate
- 導包 spring-jdbc 資料庫驅動包 c3p0連接配接池 spring-tx
- 準備好資料庫
手動管理對象測試代碼:
1)獲得資料庫連接配接 連接配接池
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/springjdbc?CharacterEncoding=UTF-8");
dataSource.setUser("root");
dataSource.setPassword("root");
2)獲得springjdbc提供的api jdbcTemplate
JdbcTemplate jt = new JdbcTemplate();
jt.setDataSource(dataSource);
3)調用JdbcTemplate方法
String sql = "insert into t_user VALUE (null,'王','199')";
int update = jt.update(sql);
System.out.println(update);
Spring 容器管理對象的方式開啟dao方法
Spring管理事務
事務的傳播行為 propagation
1、PROPAGATION_REQUIRED:如果目前沒有事務,就建立一個新事務,如果目前存在事務,就加入該事務,該設定是最常用的設定。
2、PROPAGATION_SUPPORTS:支援目前事務,如果目前存在事務,就加入該事務,如果目前不存在事務,就以非事務執行。‘
3、PROPAGATION_MANDATORY:支援目前事務,如果目前存在事務,就加入該事務,如果目前不存在事務,就抛出異常。
4、PROPAGATION_REQUIRES_NEW:建立新事務,無論目前存不存在事務,都建立新事務。
5、PROPAGATION_NOT_SUPPORTED:以非事務方式執行操作,如果目前存在事務,就把目前事務挂起。
6、PROPAGATION_NEVER:以非事務方式執行,如果目前存在事務,則抛出異常。
7、PROPAGATION_NESTED:如果目前存在事務,則在嵌套事務内執行。如果目前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。
配置xml:
<tx:advice id = "myAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="transform" isolation="DEFAULT" rollback-for="false" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="myPt" expression="execution(* com.hd.jdbc.*ServiceImpl.*(..))"></aop:pointcut>
<aop:advisor advice-ref="myAdvice" pointcut-ref="myPt"></aop:advisor>
</aop:config>
注解模式:
1. 開啟注解
<tx:annotation-driven></tx:annotation-driven>
2. 在對應的類上面加上注解,則該類的所有方法都會采取事務管理。隻對某個方法進行事務管理,在放發明上面加上注解,兩個地方都有,則以方法上面的為準
@Transactional(isolation = Isolation.DEFAULT,readOnly = false,propagation = Propagation.REQUIRED)
我所了解的隻有這麼多,希望你們不要介意,如果覺得哪裡有不對的,希望指出,加以修改。