Spring入门
来源:互联网 发布:php 两个日期相差天数 编辑:程序博客网 时间:2024/04/28 16:25
spring容器创建对象的3种方式(bean的实例化)
1,调用默认的构造函数(默认)
1)指定bean的class属性
2)class需要一个默认的空构造器
<bean id="helloWorld" class="com.jxn.HelloWorld" />
得到实例对象:HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");
2,使用静态工厂方法
1)指定class属性外
2)通过factory-method属性来指定创建bean实例的静态工厂方法
<bean id="helloWorld" class="com.jxn.HelloWorldFactory" factory-method="createInstance"></bean>
注:相当于调用了 HelloWorldFactory.createInstance();
public class HelloWorldFactory {
public static HelloWorld createInstance(){
return new HelloWorld();
}
}
得到实例对象:HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");
3,使用实例工厂方法
1)定义一个工厂类
2)通过factory-bean属性指定工厂类,通过factory-method属性指定该工厂类的非静态工厂方法
<bean id="helloWorldFactory" class="com.jxn.HelloWorldFactory" />
<bean id="HelloWorld" factory-bean="helloWorldFactory" factory-method="createInstance" />
注:相当于调用了 new HelloWorldFactory.createInstance();
public class HelloWorldFactory {
public HelloWorld createInstance(){
return new HelloWorld();
}
}
得到实例对象:HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");
注:spring调用工厂方法,在该工厂方法中,由程序员来创建对象。
创建一个springHelloworld程序
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Spring的IOC、Spring对象初始化bean时机、Spring容器生命周期
IOC指的是控制反转,把对象的创建、初始化、销毁等工作都交给Spring容器。由spring容器来控制对象的生命周期。
Spring对象初始化bean时机:
在默认情况下,只要在Spring容器中配置了一个bean,容器在启动时就会实例化该bean,单例模式。
如果在Spring配制文件时设置懒加载模式(lazy-init=”true”),在getBean时才会实例化对象。
如果scope=”prototype”时,无论lazy-init的值是什么都只会在使用时才会创建,当struts2的
action和spring容器整合的时候,action的scope设置成prototype。
spring容器生命周期:
启动spring容器
创建helloWorld对象
调用helloWorld对象的init方法,init方法是由spring容器内部调用的
在客户端提取helloWorld对象,对象调用方法
当spring容器关闭的时候,执行destroy方法:注意:前提条件:必须为单例,如果多实例,不起作用。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Spring中Bean的命名
<?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/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="helloWorld" class="reed1991.alias.HelloWorld"></bean>
<alias name="helloWorld" alias="alias1"/>
<alias name="helloWorld" alias="alias2"/>
<alias name="helloWorld" alias="alias3"/>
</beans>
此时,helloWorld为标识符,而alias1,alias2,alias3为别名,它们都可以作为Bean的键值;
HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");
HelloWorld helloWorld2 = (HelloWorld)context.getBean("alias2");
这两个语句将会等价
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
spring中的scope
1.在默认情况下,spring创建bean是单例模式
HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");
helloWorld.getLists().add("aa");
HelloWorld helloWorld2 = (HelloWorld)context.getBean("helloWorld");
helloWorld2.getLists().add("bb");
System.out.println(helloWorld.getLists().size());
System.out.println(helloWorld2.getLists().size());
则打印的都是2,因此在默认情况下,spring创建bean是单例模式.singleton 默认,
属性是共享的,所以一般情况下把数据存放在方法中的变量中.
修改applicationContext.xml
<bean id="helloWorld" class="reed1991.scope.HelloWorld" scope="prototype" ></bean>
则打印的都是1,所以,其变为多例
<bean id="helloWorld" class="reed1991.scope.HelloWorld" scope="prototype" ></bean>和
<bean id="helloWorld" class="reed1991.scope.HelloWorld" scope="prototype" lazy-init="false"></bean>
当一个bean是多例模式的情况下,lazy-init为false或者default无效
init-method
* 该方法是由spring容器执行
* 在构造函数之后执行
* 如果在构造函数之后,在调用方法之前要做一些工作,可以在init方法中完成
destroy-method
* 如果该bean是单例,则在spring容器关闭或者销毁的时候,执行该方法
* 如果该bean是多例,则spring容器不负责销毁
说明:要想让spring容器控制bean的生命周期,那么该bean必须是单例
如果该bean是多例,该bean中还有资源,关闭资源的操作由程序员完成
Spring注解@Scope("prototype")
Spring在Action上面注解@Scope("prototype")
表示每次接收一个请求创建一个Action对象..
如若改成其他,例如单例模式,则很多请求公用同一个Action.
一个注册的例子,如果没加上这个注解,注册完成后,下一个请求再注册一次,Action里会保留上一次注册的信息..
-----------------------------------------------------------------------------------------------------------------------------------------------------
springDI(依赖注入):给属性赋值就为依赖注入
1.Set方法注入
public classPerson{
private Long pid;//代表基本类型的包装类
private String pname;//String类型
private Student student;//引用类型
private List lists;
private Set sets;
private Map map;
private Properties properties;
//set和get方法
}
<?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/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="person" class="reed1991.set.Person">
<!--
property就是代表属性
在spring中基本类型(包装类型和String)都可以用value来赋值
引用类型用ref赋值
-->
<property name="pid" value="5"></property>
<property name="pname" value="reed1991"></property>
<property name="student">
<ref bean="student"/>
</property>
<property name="lists">
<list>
<value>list1</value>
<value>list2</value>
<ref bean="student"/>
</list>
</property>
<property name="sets">
<set>
<value>set1</value>
<value>set2</value>
<ref bean="student"/>
</set>
</property>
<property name="map">
<map>
<entry key="map1">
<value>map1</value>
</entry>
<entry key="map2">
<value>map2</value>
</entry>
<entry key="map3">
<ref bean="student"/>
</entry>
</map>
</property>
<property name="properties">
<props>
<prop key="prop1">
prop1
</prop>
</props>
</property>
</bean>
<bean id="student" class="reed1991.di.xml.set.Student"></bean>
</beans>
2.构造方法注入
public Person(Long pid,String pname){
this.pid = pid;
this.pname = pname;
}
public Person(String pname,Student student){
this.pname = pname;
this.student = student;
}
<bean id="person" class="reed.constructor.Person">
<!--
构造函数的参数
index 第几个参数,下标从0开始
type 参数的类型
ref 如果类型是引用类型,赋值
value 如果类型是基本类型,赋值
说明:
只能指定一个构造函数
-->
<constructor-arg index="0" type="java.lang.String" value="reed1991"></constructor-arg>
<constructor-arg index="1" ref="student"></constructor-arg>
<!--则调用第二个构造函数-->
</bean>
<bean id="student" class="reed.constructor.Student"></bean>
</beans>
ioc和di做了什么事情呢?
* 创建对象
* 给属性赋值
ioc和di的意义:
可以在一个类中引入一个接口,而给接口赋值的工作交给spring容器来做,程序员只需要在配置文件做一些配置就可以了,这样在客户端做到了完全的面向接口编程
例子
Person.java
package reed.set;public class Person {private Long pid;private String pname; public Long getPid() { return pid; } public void setPid(Long pid) {this.pid = pid;}public String getPname() {return pname;}public void setPname(String pname) {this.pname = pname;}}
applicationContext.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/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="person" class="reed.Person"> <property name="pid" value="5"></property> <property name="pname" value="王二麻子"></property> </bean> </beans>
PersonTest.java
import cn.itcast.spring.utils.SpringHelper;public class PersonTest extends SpringHelper{static{path = "reed/applicationContext.xml";} @Testpublic void test(){Person person=(Person)context.getBean("person");System.out.println(person.getPid());System.out.println(person.getPname());}}
控制台输出
5
王二麻子
通过构造函数赋值
Person.java
package reed.constructor;public class Person {private Long pid;private String pname;private Student student;public Person(Long pid,String pname,Student student){this.pid=pid;this.pname=pname;this.student=student;}public Long getPid() {return pid;}public String getPname() {return pname;}public Student getStudent() {return student;}}
Student.java
public class Student {public void say(){System.out.println("student");}}
applicationContext.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/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <!-- 构造函数的参数 index 第几个参数,下标从0开始 type 参数的类型 ref 如果类型是引用类型,赋值 value 如果类型是基本类型,赋值 说明: 只能指定一个构造函数 --> <bean id="person" class="reed.constructor.Person"> <constructor-arg index="0" type="java.lang.Long" value="5"></constructor-arg> <constructor-arg index="1" type="java.lang.String" value="reed"></constructor-arg> <constructor-arg index="2" ref="student1"></constructor-arg> </bean> <bean id="student1" class="reed.constructor.Student"></bean> </beans>
PersonTest.java
public class PersonTest extends SpringHelper{static{path = "reed/constructor/applicationContext.xml";}@Testpublic void test(){Person person = (Person)context.getBean("person"); person.getStudent().say();System.out.println(person.getPname());System.out.println(person.getPid());}}
控制台输出
student
reed
5
-----------------------------------------------------------------------------------------------------------------------------------
spring使用注解进行DI(依赖)注入
Person.java
public class Person {//@Resource(name="")这三条是等价的//@Resource()@Resource(name="student1")private Student studen;public void say(){this.studen.say();}}
Student.java
public class Student {public void say(){System.out.println("student");}}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:annotation-config></context:annotation-config> <bean id="student1" class="reed.annotation.Student"></bean> <bean id="person" class="reed.annotation.Person"></bean> </beans>
PersonTest.java
public void test(){ClassPathXmlApplicationContext applicationContext=(ClassPathXmlApplicationContext)context;Person person=(Person)applicationContext.getBean("person");person.say();applicationContext.close();}
/**
* 原理
* * 启动spring容器,并且加载配置文件
* * 会为student和person两个类创建对象
* * 当解析到<context:annotation-config></context:annotation-config>
* 会启动依赖注入的注解解析器
* * 会在纳入spring管理的bean的范围内查找看哪些bean的属性上有@Resource注解
* * 如果@Resource注解的name属性的值为"",则会把注解所在的属性的名称和spring容器中bean的id进行匹配
* 如果匹配成功,则把id对应的对象赋值给该属性,如果匹配不成功,则按照类型进行匹配,如果再匹配不成功,则报错
* * 如果@Resource注解的name属性的值不为"",会把name属性的值和spring容器中bean的id做匹配,如果匹配
* 成功,则赋值,如果匹配不成功 ,则直接报错
spring scan
原理
* * 1.启动spring容器,加载配置文件
* * 2. spring容器解析到
* <context:component-scan base-package="reed.scan"></context:component-scan>
* * 3.spring容器会在指定的包及子包中查找类上是否有@Component
* * 如果@Component注解没有写任何属性
* @Component
* public class Person{
*
* }
* ==
* <bean id="person" class="..Person">
* 如果@Component("aa")
* @Component
* public class Person{
*
* }
* ==
* <bean id="aa" class="..Person">
* * 在纳入spring管理的bean的范围内查找@Resource注解
* * 执行@Resource注解的过程
* 说明:
* xml效率比较高,但是书写比较麻烦
* 注解效率比较低,书写比较简单
package reed.scan;import javax.annotation.PostConstruct;import javax.annotation.PreDestroy;import javax.annotation.Resource;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;@Component("perso")public class Person {@Resource(name="student")private Student studen;private Long pid;public void say(){this.studen.say();}@PostConstructpublic void init(){System.out.println("init");}@PreDestroypublic void destroy(){System.out.println("destroy");}}
package reed.scan;import org.springframework.stereotype.Component;@Componentpublic class Student {public void say(){System.out.println("student");}}
import org.junit.Before;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class SpringHelper{public static ApplicationContext context;public static String path;@Beforepublic void startSpring(){context = new ClassPathXmlApplicationContext(path);}}
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"><!-- 1、导入命名空间 xmlns:context="http://www.springframework.org/schema/context" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 2、启动类扫描的注解解析器3、启动依赖注入的注解解析器--><!-- component就是beanbase-package 会在base-package的值所在的包及子包下扫描所有的类 --><context:component-scan base-package="reed.scan"></context:component-scan></beans>
package reed.scan;import org.junit.Test;import org.springframework.stereotype.Component;import reed.SpringHelper;public class PersonTest extends SpringHelper{static{path = "reed/scan/applicationContext.xml";}@Testpublic void test(){Person person = (Person)context.getBean("perso");person.say();}}
输出init
student
Spring中mvc三层用注解写
说明:如果一个类中有基本类型,并且基本类型是用spring的形式赋值的,这个时候,该类必须用xml来完成,不能用注解
一、基于@Component注解的配置
这 3 个注释和 @Component 是等效的,不过分开成这三个层次更清晰
1、@controller 控制器(注入服务) 表示层
2、@service 服务(注入dao) 业务逻辑层
3、@repository dao(实现dao访问) 数据访问层
package reed.annotation;import javax.annotation.Resource;import org.springframework.stereotype.Controller;@Controller("personAction")public class PersonAction {@Resourceprivate PersonService personService;public void savePerson(){this.personService.savePerson();}}
package reed.annotation;import org.springframework.stereotype.Repository;@Repository("personDao")public class PersonDaoImpl implements PersonDao{@Overridepublic void savePerson() {System.out.println("save person");}}
package reed.annotation;import javax.annotation.Resource;import org.springframework.stereotype.Controller;@Controller("personAction")public class PersonAction {@Resourceprivate PersonService personService;public void savePerson(){this.personService.savePerson();}}
package reed.annotation;import org.junit.Test;import reed.utils.SpringHelper;public class PersonTest extends SpringHelper{static{path="reed/annotation/applicationContext.xml";}@Testpublic void test(){PersonAction personAction=(PersonAction)context.getBean("personAction");personAction.savePerson();}}
ersion="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"><context:component-scan base-package="reed.annotation"></context:component-scan></beans>
输出save person
Spring中的持久层数据访问Dao注解这样使用@Repository(exampleDao),括号里的值是代表什么起什么作用,也可以单独使用@Repository不加边的东西,
问题是加了后边有什么好处?
就是bean的名称,如果不加括号里面的spring管理的bean默认及时类名首字母小写,
好处就是如果有多个同一个类型的bean,可以加上名称自己区分,举个例子吧
一个接口有多个实现类,因为spring注入默认按类型查找,只是注入就要报错,你给每个实现类上的bean加上名字,
注入的时候再加上@Qualifier(你要注入bean的名称)就行了
--------------------------------------------------------------------------------------------------------------------------------------
AOP的一些概念
* 切面
日志、安全性的框架、权限的检查等,总之和业务逻辑没有关系的都可以看做切面
* 通知
切面中的方法
* 切入点
只有符合切入点,才能把通知和目标方法结合在一起
* 连接点
客户端调用的方法
织入: 形成代理方法的过程
* 代理对象的方法=通知+目标方法
* aop:做到了代码块的重用
-----------------------------------------------------------------------------------------------------------------------------------
Spring切入点表达式常用写法
Spring AOP 用户可能会经常使用 execution切入点指示符。执行表达式的格式如下:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)
modifiers-pattern:修饰符
ret-type-pattern:返回值
declaring-type-pattern?访问权限
name-pattern:方法名
(param-pattern):参数
throws-pattern?:异常
任意公共方法的执行:
execution(public * *(..))
任何一个名字以“set”开始的方法的执行:
execution(* set*(..))
AccountService接口定义的任意方法的执行:
execution(* com.xyz.service.AccountService.*(..))
在service包中定义的任意方法的执行:
execution(* com.xyz.service.*.*(..))
在service包或其子包中定义的任意方法的执行:
execution(* com.xyz.service..*.*(..))
spring中注解
Spring中什么时候用@service,什么时候用@Resource
当你需要定义某个类为一个bean,则在这个类的类名前一行使用@Service("XXX"),就相当于讲这个类定义为一个bean,bean名称为XXX;
当需要在某个类中定义一个属性,并且该属性是一个已存在的bean,要为该属性赋值或注入时在该属性上一行使用@Resource(name="xxx"),相当于为该属性注入一个名称为xxx的bean。
@Autowire注解和@Resource一样,同样也可以标注在字段或属性的setter方法上,但它默认按类型装配。
@Transactional(readOnly=true)表明所注解的方法或类只是读取数据。
@Transactional(readOnly=false)表明所注解的方法或类是增加,删除,修改数据。
---------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------
- Spring 入门
- Spring 入门
- Spring 入门
- Spring入门
- Spring入门
- Spring入门
- Spring入门
- Spring 入门
- spring 入门
- Spring入门
- Spring入门
- Spring入门
- Spring入门
- spring入门
- Spring入门
- spring 入门
- Spring入门
- Spring入门
- 从对方的的立场看问题
- TCP/IP协议学习(1)—数据链路层
- 利用Office组件MODI识别图片上的文本 - [技巧攻略]
- 写一个宏,将一个数的奇数位和偶数位交换
- 从赞美和欣赏别人开始
- Spring入门
- TCP协议,UDP协议,TCP/IP的区别
- 【JZOJ4887】【NOIP2016提高A组集训第13场11.11】最大匹配
- 【数据结构与算法】计数排序
- VR系列——Oculus Audio sdk文档:二、Oculus音频SDK指南(1~2)——SDK内容和特点及要求
- GDAL学习笔记——OGR投影(一)
- 使用MODI(Microsoft Office Document Imaging)识别中文,但无法区分段落
- Unity3D开发小贴士(七)Lua里扩展C#对象
- Java应用缓存介绍与LRU(Least Recently Used)算法