Spring
方便解耦,简化开发(Spring就是一个大工厂,可以将所有对象创建和依赖关系维护交给Spring管理)
AOP 编程的支持,Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
声明式事务的支持,只需要通过配置就可以完成对事务的管理,而无需手动编程
方便程序测试,Spring对junit4支持,可以通过注解方便测试Spring程序
方便继承各种优秀框架,Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(Struts Hibernate Mybatis 等等)的直接支持
降低JavaEE API的使用难度,Spring对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低
整个项目中装配Bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象,有两个核心分别是IOC(控制反转)和AOP(面向切面编程)
IOC控制反转,简单说就是讲new关键字创建对象的权利交给Spring框架来管理,开发者只关注业务逻辑处理
AOP面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术,利用AOP可以对业务逻辑的各个部分进行隔离,降低业务逻辑之间的耦合度,提高代码的可重用性,同时提高了开发的效率,事务管理、日志文件打印通常用到AOP
需要的jar包:
最后需要commons-logging
maven中pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>
Hello类:
public class Hello {
private String name;
public void setName(String name) {
this.name=name;
}
public void show() {
System.out.println("hello"+name);
}
}
测试类:
public class Test {
public static void main(String[] args) {
//解析beans.xml文件生成管理相应的bean对象
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
Hello hello = (Hello)context.getBean("hello");
hello.show();
}
}
用maven是舒服,idea中项目结构:
还有个Beans.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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- bean就是java对象 由spring来创建和管理的 -->
<bean name="hello" class="com.qianjiang.bean.Hello">
<property name="name" value="张三"></property>
</bean>
</beans>
Hello对象是由spring容器创建。
Hello对象属性是由spring容器来设置
这个过程就叫控制反转:
控制:是谁来控制对象的创建;传统的应用程序对象的创建是由程序本身控制的。使用spring后,是由spring来创建对象
反转:值程序本身不去创建对象,而变为被动接受的对象
总结:以前对象是由程序本身来创建,使用spring后,程序变为被动接受spring创建好的对象。控制反转—依赖注入
使用ioc来创建对象的三种方式
1.使用无参的构造方法来创建
private String name;
public Hello() {
System.out.println("无参构造创建对象");
}
public void setName(String name) {
this.name=name;
}
public void show() {
System.out.println("hello"+name);
}
Beans.xml文件
别名:
<alias name ="user" alias ="username">
bean的配置:
id:bean的唯一标识符,也就是我们对象名
class:bean对象所对应的限定名(包名+类名)
name:别名,可以取多个别名
import
将多个配置文件,导入合并为一个总文件(applicationContext.xml),最后使用的时候也就用这个总文件
<import resource="beans1.xml">
<import resource ="bean2.xml">
<import resource ="bean3.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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- bean就是java对象 由spring来创建和管理的 -->
<bean id="hello" class="com.qianjiang.bean.Hello">
<property name="name" value="spring"></property>
</bean>
</beans>
2.通过有参构造方法来创建对象:
public class Hello {
private String name;
public Hello(String name) {
this.name =name;
System.out.println("有参构造创建对象");
}
public void show() {
System.out.println("hello="+name);
}
}
Beans.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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- bean就是java对象 右spring来创建和管理的 -->
<bean id="hello" class="com.qianjiang.bean.Hello">
//通过下角标
//<constructor-arg index="0" value="spring">
//</constructor-arg>
//指定参数名称
// <constructor-arg name="name" value="spring"></constructor-arg>
<constructor-arg type="java.lang.String" value="spring"></constructor-arg>
</bean>
</beans>
index指构造方法参数下标从0开始
name指的是构造方法的参数名称
type通过参数类型设置
3.通过工厂方法来创建对象
静态工厂:
public class HelloFactory {
public static Hello newInstance(String name) {
return new Hello(name);
}
}
Beans.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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- bean就是java对象 右spring来创建和管理的 -->
<bean id="hello" class="com.qianjiang.factory.HelloFactory" factory-method="newInstance">
<constructor-arg type="java.lang.String" value="spring"></constructor-arg>
</bean>
</beans>
动态工厂:
public class HelloDyFactory {
public Hello newInstance(String name) {
return new Hello(name);
}
}
Beans.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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- bean就是java对象 由spring来创建和管理的 -->
<bean id="helloFactory" class="com.qianjiang.factory.HelloDyFactory"></bean>
<bean id="hello" class="com.qianjiang.factory.HelloFactory" factory-bean="helloFactory" factory-method="newInstance">
<constructor-arg type="java.lang.String" value="spring"></constructor-arg>
</bean>
</beans>
配置文件
id是bean的标识符 要唯一,如果没有配置id name默认标识符,都有id name 那么name是别名,name可以设置多个别名 分隔符可以使空格 逗号 分号
<alias name="" alias=""/>
class是bean 的全限定名=包名+类名
没有配置id和name,那么可以根据applicationContext.getBean(Class)获取对象
导入其他资源 import
依赖注入(DI)
依赖:指的是Bean对象的创建依赖于容器Bean对象的依赖资源
注入:指的Bean对象所依赖的资源,由容器来设置和装配
1.构造器注入
2.set注入
public class ChinaGirlFriend {
private String language;
public ChinaGirlFriend(){
}
public ChinaGirlFriend(String language){
this.language=language;
}
public String speak(){
return language;
}
public void setLanguage(String language) {
this.language = language;
}
}
public class DataType {
private String s1;//特殊字符
private String s2;//特殊字符
private User innerBean;//内部类
private List<String> list;
private String[] array;
private Set<String> set;
private Map<String,String> map;
private Properties properties;
private String emptyValue;//注入空字符串
private String nullValue = "init null";//注入null值
public void setS1(String s1) {
this.s1 = s1;
}
public void setS2(String s2) {
this.s2 = s2;
}
public void setInnerBean(User innerBean) {
this.innerBean = innerBean;
}
public void setList(List<String> list) {
this.list = list;
}
public void setArray(String[] array) {
this.array = array;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public void setEmptyValue(String emptyValue) {
this.emptyValue = emptyValue;
}
public void setNullValue(String nullValue) {
this.nullValue = nullValue;
}
public void printValue(){
System.out.println("特殊字符串1"+this.s1);
System.out.println("特殊字符串2"+this.s2);
System.out.println("内部类"+this.innerBean.getUsername());
System.out.println("list属性"+this.list);
System.out.println("数组属性"+this.array);
System.out.println("set属性"+this.set);
System.out.println("map属性"+this.map);
System.out.println("properties属性"+this.properties);
System.out.println("注入空字符串"+this.emptyValue);
System.out.println("注入null值"+this.nullValue);
}
}
Beans.xml文件配置:
依次是数组注入、List注入、set注入、Map注入、null注入、Properities注入
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.ddb.spring.auto"/>
<!--set注入(无参构造)-->
<bean class="com.ddb.spring.set.ChinaGirlFriend" id="chinaGirlFriend2">
<property name="language" value="中文2"></property>
</bean>
<!--通过有参构造-->
<bean class="com.ddb.spring.set.ChinaGirlFriend" id="chinaGirlFriend">
<constructor-arg index="0" value="中文"> </constructor-arg>
</bean>
<!--p的命名空间-->
<bean class="com.ddb.spring.set.ChinaGirlFriend" id="chinaGirlFriend3" p:language="中文3"></bean>
<bean id="dataType" class="com.ddb.spring.set.DataType">
<!--特殊字符一-->
<property name="s1">
<value><![CDATA[EP&G]]></value>
</property>
<!--特殊字符你二-->
<property name="s2">
<value>EP&G</value>
</property>
<!--定义内部bean-->
<property name="innerBean">
<bean class="com.ddb.spring.type.User">
<property name="username" value="sunYun"/>
</bean>
</property>
<!--注入list类型-->
<property name="list">
<list>
<value>兵乓球</value>
<value>羽毛球</value>
<value>篮球</value>
<value>足球</value>
</list>
</property>
<!--注入数组类型-->
<property name="array">
<array>
<value>十元</value>
<value>二十元</value>
<value>一百元</value>
</array>
</property>
<!--注入set类型-->
<property name="set">
<set>
<value>王一博</value>
<value>杨洋</value>
<value>王俊凯</value>
</set>
</property>
<!--注入map类型-->
<property name="map">
<map>
<entry key="tableTennis" value="兵乓球"/>
<entry value="羽毛球" key="badminton"/>
<entry key="football" value="足球"/>
<entry value="篮球" key="basketball"/>
</map>
</property>
<!--注入properties-->
<property name="properties">
<props>
<prop key="学号">8399310</prop>
<prop key="性别">男</prop>
<prop key="姓名">douDou</prop>
</props>
</property>
<!--注入空的字符串-->
<property name="emptyValue">
<value></value>
</property>
<!--注入null-->
<property name="nullValue">
<null></null>
</property>
</bean>
</beans>
我们可以使用p命令和c命令空间进行注入,需要导入xml约束
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
<!--p命名空间的注入,可以直接注入到属性的值-->
<bean id="hello2" class="com.qj.pojo.Hello" p:name="Spring"/>
<!--c命名空间的注入,通过有参构造注入到属性的值-->
<bean id="hello3" class="com.qj.pojo.Hello" c:name="Spring1"/>
Bean的作用域
在spring中,那些组成应用程序的主体及Spring Ioc容器所管理的对象,被称为bean.简单说bean就是由Ioc容器初始化。装配及管理的对象
默认是单例模式(scope=“singleton”)
@Test
public void test2(){
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("bean.xml");
Hello hello = (Hello) applicationContext.getBean("hello3",Hello.class);
Hello hello1 =(Hello) applicationContext.getBean("hello3",Hello.class);
System.out.println(hello==hello1);//true
}
原型模式,每次从容器取get的时候,都会产生一个新对象scope=“prototype”
@Test
public void test2(){
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("bean.xml");
Hello hello = (Hello) applicationContext.getBean("hello3",Hello.class);
Hello hello1 =(Hello) applicationContext.getBean("hello3",Hello.class);
System.out.println(hello==hello1);//false
}
其余request、session、application、这些在web开发中使用到,纯Java后台用不到.
3.request
当一个bean的作用域为request,表示再一次HTTP请求中,一个bean定义一个实例;即每个http请求都会有各自的bean实例。他们依据某个bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext情形下有效
4.session
同一个HTTP Session共享一个Bean,不同Session使用不同Bean,仅适用于webApplicationContext环境。当HTTPSession最终被废弃的时候,在该HTTP Session作用域内的bean也会被废弃掉
自动装配
1、在xml中显示定义
<bean id="cat" class="com.qj.pojo.Cat"></bean>
<bean id="dog" class="com.qj.pojo.Dog"></bean>
<bean id="people" class="com.qj.pojo.People">
<property name="name" value="豆豆"></property>
<property name="cat" ref="cat"></property>
<property name="dog" ref="dog"></property>
</bean>
2、autowire=""
byName自动装配
byname:会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid
<bean id="people" class="com.qj.pojo.People" autowire="byName">
<property name="name" value="豆豆"></property>
</bean>
byType自动装配
会自动在容器上下文查找,和自己对应属性类型相同的bean
<!-- <bean id="cat" class="com.qj.pojo.Cat"></bean>-->
<!-- <bean id="dog12" class="com.qj.pojo.Dog"></bean>-->
<bean class="com.qj.pojo.Cat"></bean>
<bean class="com.qj.pojo.Dog"></bean>
<bean id="people" class="com.qj.pojo.People" autowire="byType">
<property name="name" value="豆豆"></property>
</bean>
注解自动装配
导入约束:
xmlns:context="http://www.springframework.org/schema/context"
配置注解的支持
<context:annotation-config/>
配置文件如下:
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:annotation-config/>
<bean id="cat" class="com.qj.pojo.Cat"></bean>
<bean id="dog" class="com.qj.pojo.Dog"></bean>
<bean id="people" class="com.qj.pojo.People"></bean>
</beans>
@Autowired
直接在属性上使用即可,也可以在set方法中使用,使用Autowired我们可以不用编写set方法了,前提配置ok(自动装配的属性在ioc容器中存在)
@Autowired
@Qualifier()两个一起使用去找到要装配的属性(指定注入Bean的名称)
<bean id="cat1" class="com.qj.pojo.Cat"></bean>
<bean id="cat2" class="com.qj.pojo.Cat"></bean>
<bean id="cat3" class="com.qj.pojo.Cat"></bean>
<bean id="dog1" class="com.qj.pojo.Dog"></bean>
<bean id="dog2" class="com.qj.pojo.Dog"></bean>
<bean id="dog3" class="com.qj.pojo.Dog"></bean>
<bean id="people" class="com.qj.pojo.People"></bean>
@Autowired
@Qualifier(value = "dog1")
private Dog dog;
@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Nullable 字段标记了这个注解,说明这个字段可以为null
@Resource
@Resource(name = "dog1")
private Dog dog;
@Resource 和@Autowired的区别
都是自动装配,都可以放在属性字段上
@Autowired通过byType的方式实现,而且必须要求这个对象存在
@Resource默认通过byName的方式实现,如果找不到名字,则通过byType实现,如果两个都找不到的情况就报错
使用注解开发(重要!)
在spring4之后使用注解开发,必须保证aop的包导入了,使用需要导入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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:annotation-config/>
<!--在这个包下,spring都能扫描到,已经装配上-->
<context:component-scan base-package="com.qj"/>
</beans>
@Component
//<bean id="user " class="com.qj.pojo.user">
public class People {
@Value("spring")
//<property name="name" value="spring"/>
public void setName(String name) {
this.name = name;
}
}
跟@Component有几个衍生的注解,差不多用法
dao --------@Repository
sercice------@Service
controller----@Controller
都代表将某个类注册到Spring中,装配bean
配置类
配置类:
package com.doupijiang.config;
import com.doupijiang.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.doupijiang.pojo")
public class UserConfig {
//这个方法名就相当于之前配置文件bean的id
//返回值相当于bean标签的class属性
@Bean
public User getUserName(){
return new User();
}
}
package com.doupijiang.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class User {
private String name;
@Value("douPiJiang")
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void show(){
System.out.println("java配置类实现"+getName());
}
}
@Test
public void test(){
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(UserConfig.class);
User user =(User) applicationContext.getBean("getUserName");
user.show();
}
aop
这个时候增加一个jar包:
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
1、方式一:原生spring api接口
动态代理代理的是接口
UserService接口:
public interface UserService {
void add();
void delete();
void update();
void select();
}
UserServiceImp实现类:
public class UserServiceImp implements UserService{
public void add() {
System.out.println("进行了add方法");
}
public void delete() {
System.out.println("进行了delete方法");
}
public void update() {
System.out.println("进行了update方法");
}
public void select() {
System.out.println("进行了select方法");
}
}
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class BeforeLog implements MethodBeforeAdvice {
/**
*
* @param:参数method要执行的目标对象的方法
* @param:参数object
* @param:参数o执行的对象
* @throws Throwable
*/
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("方法之前"+method.getName()+"被执行了");
}
}
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class AfterLog implements AfterReturningAdvice {
/**
*
* @param o:返回值
* @param method:执行对象的方法名
* @param objects:参数
* @param o1:执行的对象
* @throws Throwable
*/
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("方法之后"+method.getName()+"执行了");
}
}
application.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/sche