Spring优势(作用)
(1)Spring是一站式框架,因为Spring框架的性质是属于容器性质,容器中装了什么对象就有什么功能,所以可以一站式。
(2)不仅不排斥其他框架、还能其他框架帮忙管理对象。
(3)AOP支持
(4)基于IOC思想
(5)Spring jdbc
(6)aop 事务
(7)Junit测试支持。
Spring框架搭建(入门)
1、创建项目(Maven)
修改Maven配置
2、导包(pom.xml)
3、创建对象(User)
public class User {
private Integer userId;
private String name;
private String password;
}
4、书写配置:注册对象到容器中
配置文件名字和目录问题:
文件名和目录都可以任意
建议:src/applicationContext.xml
在pom.xml中加入依赖:
<!-- spring包 core、web、oxm、tx、jdbc、webmvc、aop、context、test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
导入约束
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">
</beans>
将User对象交给Spring管理
<bean name="user" class="com.huadian.a_helloworld.User"></bean>
测试一下
创建一个Demo类;
@Test
public void fun(){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) ac.getBean("user");
System.out.println(user);
}
输出显示:
Spring概念
1.Spring思想
IOC:(Inverse of control) 反转控制
将我们创建对象的方式反转了。
以前对象的创建由我们开发人员自己维护,包括依赖关系也是我们自己注入的
使用Spring之后,对象的创建以及依赖关系可以由Spring完成创建以及注入
反转控制:就是反转了对象创建的方式,从我们自己创建反转给了程序(Spring)
DI:Dependency Injection 依赖注入
注入的方式:
set方法注入;先为属性添加set方法,然后如下:
<bean name="car" class="com.huadian.c_injection.Car">
<property name="name" value="公交车"></property>
</bean>
name为添加的set方法名后面所对应的属性。
如果通过set方法注入属性,那么spring会通过默认的空参构造方法来实例化对象,所以如果在类中写了一个带有参数的构造方法,一定要把空参数的构造方法写上,否则spring没有办法实例化对象,导致报错。
构造方法注入;需要为类添加好构造函数,
<bean name="user" class="com.huadian.c_injection.User">
<constructor-arg name="name" value="123"></constructor-arg>
<constructor-arg name="car" ref="car"></constructor-arg>
</bean>
注解的方式注入:
先在配置文件中配置:
xmlns:p="http://www.springframework.org/schema/p"
<bean name="user" class="com.huadian.c_injection.User"
p:name="huadian"
p:car-ref="car"></bean>
2.Spring中工厂(容器)
工厂factory
设计模式,提供的方法一般是静态的,
帮我们生产出对象的。
如:User user = XXXFactory.createUser();
ApplicationContext和BeanFactory
BeanFactory:Spring原始接口,针对原始接口的实现类功能较为单一
该接口是在获取对象的时候才会创建对象。空间换时间。
BeanFactory的子接口,其常用实现类是org.springframework.context.support.FileSystemXmlApplicationContext和org.springframework.context.support.ClassXmlAplicationContext。
ApplicationContext:容器在创建的时候,容器里面配置的所有对象会被创建,并且提供更多的功能。时间换空间。
有2个实现类:
ClassPathXmlApplicationContext
从类路径加载配置文件
new ClassPathXmlApplicationContext( "applicationContext.xml" );
FileSystemXmlApplicationContext
从硬盘绝对路径中加载配置文件
New FileSystemXmlApplicationContext(“d:/xxx/yyy/zzz”)
一个算法的好与不好:时间复杂度和空间复杂度。
Spring配置详
Bean元素
Bean元素:使用该元素描述需要Spring容器管理的对象
class属性:被管理对象的完整类名。
name属性:给被管理的对象起的名字,获得对象时根据该name获取对象。(尽量使用)
id属性:功能与name属性一样,但是不能重复且不能使用特殊字符。(原始)
Bean元素的Scope属性:
Prototype:多例原型:将标记对象变成多例类型,每次获取的时候都创建一个新的对象
Singleton:单例(默认值):将标记对象变成单例类型,每次获取的时候都创建对象都是同一个
Request
Web环境下,对象与Request生命周期一致
Session
Web环境下,对象与Session生命周期一致
Prototype
例:
@Repository("user")//dao层,实体层
@Scope("prototype")
public class User {
@Value("111")
private Integer userId;
@Value("aaa")
private String name;
private String password;
先将user类标记成多例,
配置配置文件:
<context:component-scan base-package="com.huadian.d_annotion"></context:component-scan>
<bean name="car2" class="com.huadian.d_annotion.Car">
<property name="name" value="gffs"></property>
</bean>
添加一个初始方法:
@PostConstruct//在对象别创建后调用 init-method
public void init(){
System.out.println("我是初始化方法!");
}
测试类:
@Test
public void fun() {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext( "d_applicationContext.xml" );
Object user1 = ac.getBean( "user" );
Object user2 = ac.getBean( "user" );
System.out.println( user1==user2);
}
可以看到初始方法调用两次,说明创建了两个对象,user1和user2也不相同。
Singleton
例:
@Scope("singleton")
设置成单例,也可以不设置,默认为单例。
方法只掉用了一次,并且user1==user2
说明这是同一个对象。
生命周期
init-method:指定初始化方法,spring在对象创建之后立即调用
destroy-method:指定摧毁方法,spring容器在关闭的时候 会销毁所有容器中的 对象之前调用
<bean name="user" class="com.huadian.a_helloworld.User"
init-method="init"
destroy-method="destory">
</bean>
这样可以在user类中添加init和destory方法。
Spring创建对象的方式(了解)
无参的构造方法 的方式
<bean name="user2" class="com.huadian.a_helloworld.User"></bean>-->
静态工厂实例化 的方式
<!--将User对象交给Spring管理-->
<bean name="user" class="com.huadian.b_create_bean.User" factory-method="getUserObject"></bean>
user类中
public class User {
private Integer userId;
private String name;
private String password;
public User() {
System.out.println("无参数构造方法");
}
public static User getUserObject() {
System.out.println("静态工厂实例化方法");
return null;
}
Spring的分模块配置
将不同的模块配置放到不同的配置文件中。
每个配置文件都需要导入对应约束
ApplicationContext.xml
applicationContext-Dao.xml:所有DAO对象配置
applicationContext-Service.xml:所有Service对象配置
<import resource="b_1applicationContext.xml"></import>
在其他的配置文件中导入其他文件的配置。
Spring属性注入及方式:
方式一:Set方法注入(最重要)
<bean name="car" class="com.huadian.c_injection.Car">
<property name="name" value="公交车"></property>
</bean>
<bean name="user" class="com.huadian.c_injection.User">
<property name="name" value="lw"></property>
<property name="car" ref="car"></property>
</bean>
使用property 标签。
需要注意的是,值类型用value,对象类型用 ref。
方式二:构造函数注入
<bean name="user" class="com.huadian.c_injection.User">
<!--<constructor-arg name="userId" value="1"></constructor-arg>-->
<constructor-arg name="name" value="123"></constructor-arg>
<constructor-arg name="car" ref="car"></constructor-arg>
</bean>
<bean name="car" class="com.huadian.c_injection.Car">
<property name="name" value="自行车"></property>
</bean>
使用constructor-arg标签。
index可以设置构造函数属性的顺序,例:写两个构造函数,
public User(String name, Car car) {
System.out.println("String name, Car car");
this.name = name;
this.car = car;
}
public User(Car car ,String name) {
System.out.println("Car car ,String name");
this.name = name;
this.car = car;
}
<constructor-arg name="name" value="123" index="0"></constructor-arg>
可以看到调用了不同的函数。
方式三:p名称空间注入
需要先添加约束
xmlns:p="http://www.springframework.org/schema/p"
<bean name="user" class="com.huadian.c_injection.User"
p:name="huadian"
p:car-ref="car"></bean>
<bean name="car" class="com.huadian.c_injection.Car">
<property name="name" value="拖拉机"></property>
</bean>
方式四:spel注入(类似OGNL)
<!--spel注入方式-->
<bean name="user2" class="com.huadian.c_injection.User">
<property name="name" value="#{user.name}"></property>
<!--<property name="car" ref="car.name"></property>-->
</bean>
复杂类型注入方式(数组,List,Map,Properties)
public class User {
private Integer userId;
private String name;
private String password;
private Car car;
private String[] array;
private List list;
private Map map;
private Properties prop;
<property name="array">
<array>
<value>黄色</value>
<value>绿色</value>
</array>
</property>
<property name="list">
<list>
<value>喜羊羊</value>
<value>语言</value>
<ref bean="car"></ref>
</list>
</property>
<property name="map">
<map>
<entry key="name" value="老哥"></entry>
<entry key="age" value="18"></entry>
</map>
</property>
<property name="prop">
<props>
<prop key="addr">车管所</prop>
<prop key="higet">2</prop>
</props>
</property>
使用注解配置Spring
开启使用注解代理配置
<context:component-scan base-package="com.huadian.d_annotion"></context:component-scan>
将对象注册到容器中
@Componet,@Service(service层),@Controller(web层),@Repository(dao层实体层)
//@Component("user")
@Repository("user")//dao层,实体层
//@Service("user")
//@Scope("prototype")
//@Scope("singleton")
修改Scope
@Scope(“singleton|prototype|request|session”)
属性注入
方式一:通过反射的field赋值,破坏了封装性
方式二:通过set方法赋值,推荐使用
引用类型
@Autowired
会自动装配。原理是查找不同类型的对象。
@Autowired+@Qualifier
当出现多个相同类型不同名称的对象时,@Autowired无法找到具体哪一个,这时候需要使用@Qualifier,通过使用@Qualifier注解来告诉spring是哪一个对象
@Resource
@Resource(name=“car2”)手动指定哪一个对象。
Spring整合Junit测试
在测试类中添加注解:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:e_applicationContext.xml")
public class Demo {
@Autowired
private User user;
@Test
public void fun(){
System.out.println(user);
}
}
Spring AOP思想
可以解决中文乱码、跨域的解决、事务,用户未登入不能访问个人中心等页面的问题。
Spring实现AOP的原理
(1)动态代理(优先):被代理的对象必须要实现接口,才能实现产生代理对象,如果没有接口将不能实现动态代理实现。
(2)cglib代理(没有接口):第三方代理技术,cglib代理可以对任何类生产代理,代理的原理是对目标对象进行继承,如果目标对象被final修饰将无法被cglib代理。
AOP专业术语
增强(Advice)
添加一些特殊的功能我们添加的功能也就是增强
比如:添加日志、管理事务。
切点(Pointcut)
需要增强的位置。
连接点(Joinpoint)
连接点就是程序执行的某个特定的位置,如:类开始初始化前、类初始化后、类的某个方法调用前、类的某个方法调用后、方法抛出异常后等。Spring 只支持类的方法前、后、抛出异常后的连接点。
切面(Aspect)
切面由切点和增强(或引介)组成,或者只由增强(或引介)实现
目标对象(Target)
被代理(增强)的对象
AOP代理(AOP proxy)
一个类被AOP织入后生成出了一个结果类
织入(Weaving)
织入就是将增强添加到目标类具体连接点上的过程。
例:结构
userservice
public interface UserService {
public void add();
public void del();
public void modify();
}
userserviceimpl
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("add");
}
@Override
public void del() {
System.out.println("del");
}
@Override
public void modify() {
System.out.println("modify");
}
}
myadvice类
public class MyAdvice {
public void before(){
System.out.println("这是前置通知");
}
public void after(){
System.out.println("这是后置通知");
}
}
配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">
<bean name="UserService" class="com.huadian.h_spring_aop.service.impl.UserServiceImpl"></bean>
<bean name="MyAdvice" class="com.huadian.h_spring_aop.MyAdvice"></bean>
<aop:config>
<aop:pointcut id="pc" expression="execution(* com.huadian.h_spring_aop.service.impl.*ServiceImpl.*(..))"></aop:pointcut>
<aop:aspect ref="MyAdvice">
<aop:before method="before" pointcut-ref="pc"></aop:before>
<aop:after method="after" pointcut-ref="pc"></aop:after>
</aop:aspect>
</aop:config>
</beans>
测试类demo:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:h_applicationContext.xml")
public class Demo {
@Autowired
private UserService userService;
@Test
public void fun(){
userService.add();
}
}
结果