一、IOC
1.1对象的创建
-
使用无参构造(默认)
-
使用有参构造
-
参数名
<beans> <bean id="beanOne" class="x.y.ThingOne"> <constructor-arg ref="beanTwo"/> <constructor-arg ref="beanThree"/> </bean> </beans>
-
类型
<!--多个同类属性无法识别,不建议--> <beans> <bean id="beanOne" class="x.y.ThingOne"> <constructor-arg type="java.lang.Integer" value="12"/> <constructor-arg type="java.lang.String" value="BeanName"/> </bean> </beans>
-
下标
<beans> <bean id="beanOne" class="x.y.ThingOne"> <constructor-arg index="0" value="12"/> <constructor-arg index="1" value="BeanName"/> </bean> </beans>
-
在配置文件加载的时候对象就已经创建了,且容器默认单例。
1.2、spring配置
-
别名
<!--可以使用subsystemA获取myApp对应的对象--> <alias name="myApp" alias="subsystemA"/>
-
Bean的配置
- id:唯一标识符
- class:所对应的全限定名
- name:可以看作别名,但可以多个 name=“name,name1” (分隔符空格逗号分号都可以)
-
import
<!--一般用于团队开发,将多个配置导入合并为一个--> <import resource="beans.xml"/>
二、DI依赖注入
2.1、构造器注入
见上文…
2.2、Set方式注入
- 依赖注入:本质是set注入
- 依赖:Bean对象的创建依赖于容器
- 注入:Bean对象的所有属性由容器注入
<!-- 可以注入的内容 bean | ref | idref | list | set | map | props | value | null-->
<!--注入字符串-->
<property name="name" value="name"/>
<!--注入引用-->
<property name="address" ref="address"/>
<!--注入数组-->
<property name="someMap">
<array>
<value>12</value>
<value>25</value>
</array>
</property>
<!--注入list-->
<property name="hobbies">
<list>
<value>写作业</value>
<value>学习</value>
</list>
</property>
<!--注入map-->
<property name="card">
<map>
<entry key="an entry" value="just some string"/>
<entry key ="a ref" value-ref="myDataSource"/>
</map>
</property>
<!--注入set-->
<property name="games">
<set>
<value>LOL</value>
<value>EVO</value>
</set>
</property>
<!--注入null-->
<property name="games">
<null/>
</property>
<!--注入null-->
<property name="info">
<props>
<prop key="学号" >20152351</prop>
<prop key="url" >http://url.xiaoming.cn</prop>
</props>
</property>
2.3、拓展方式注入
导入p或c命名空间的约束
<!-- p -->
<beans xmlns:p="http://www.springframework.org/schema/p">
</beans>
<!-- c -->
<beans xmlns:c="http://www.springframework.org/schema/c">
</beans>
-
p命名空间
property:可以直接注入属性值,对应set注入
<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" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean name="classic" class="com.example.ExampleBean"> <property name="email" value="someone@somewhere.com"/> </bean> <bean name="p-namespace" class="com.example.ExampleBean" p:email="someone@somewhere.com"/> </beans>
-
c命名空间
对应构造器注入
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="beanTwo" class="x.y.ThingTwo"/> <bean id="beanThree" class="x.y.ThingThree"/> <!-- traditional declaration with optional argument names --> <bean id="beanOne" class="x.y.ThingOne"> <constructor-arg name="thingTwo" ref="beanTwo"/> <constructor-arg name="thingThree" ref="beanThree"/> <constructor-arg name="email" value="something@somewhere.com"/> </bean> <!-- c-namespace declaration with argument names --> <bean id="beanOne" class="x.y.ThingOne" c:thingTwo-ref="beanTwo" c:thingThree-ref="beanThree" c:email="something@somewhere.com"/> </beans>
2.4、Bean作用域
- singleton:(Default) Scopes a single bean definition to a single object instance for each Spring IoC container.
- prototype:Scopes a single bean definition to any number of object instances.
- request:Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
- session: Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
- application:Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring applicationContext.
- websocket: Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.
- 单例模式:spring默认的机制,只生成一个对象
- 原型模式:每次从容器get都会生成新对象
- request、session、application只能在web项目开发中使用
三、自动装配
3.1、装配方式
自动装配是spring满足Bean依赖的一种方式
spring会在上下文中自动寻找,并自动给Bean装配属性
spring中的三种配置方式:
- 在xml中手动配置
- 在Java文件中配置
- 隐式的自动配置
3.2、spring装配
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--按照id找set方法后面的名字-->
<bean id="beanOne" class="x.y.ThingOne" autowire="byName"/>
<!--但是type必须唯一 -->
<bean id="beanOne" class="x.y.ThingOne" autowire="byType"/>
</beans>
byName:需要保证所有的bean的id唯一,并且Bean需要和自动注入的属性的set方法的值一致
byType:需要保证所有的bean的类型唯一,并且Bean需要和自动注入的属性的类型一致
3.3、注解实现
jdk1.5支持,spring2.5以后支持注解
使用注解需要:
- 导入约束-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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
- @Autowired(required=false)用在属性或set方法上,自动注入属性,配置需要符合nytype byname
- @Nullable字段可以为空且不报错
- @Qualifier(value=“beanName”) 指定注入哪一个对象
- @Resource (name="…")注入(兼容byname bytype两种注入)
四、使用注解开发
-
在spring4之后,必须要保证AOP的包已经导入,才可以使用
-
使用注解需要增加context依赖
<!--扫描包--> <context:component-scan base-package="cn.yu.beans"/> <context:annotation-config />
4.1、Bean
- @component:添加在类上面,装配Bean,相当于beans内的bean标签
4.2、属性如何注入
- @Value(“XXX”):注入属性,相当于property的name和value
4.3、衍生的注解
在web开发中,我们会按照mvc架构进行分层,dao\controller\service等,@component有这些衍生注解
- dao–@Repository
- controller–@Controller
- service–@Service
他们的功能都是一样的,把类交给Spring来进行管理,在spring中进行注册,装配Bean
4.4、自动装配
第三节
4.5、作用域
<!-- 具体看2.4 -->
<bean id="myCommand" class="fiona.apple.AsyncCommand" scope="prototype">
<!-- scope的值有singleton(单例模式)、prototype(原型模式)、request、session、application、websocket-->
</bean>
@Scope("prototype")
public class Bean{
//属性和方法
}
4.6、对比
- xml适用范围更广、维护简单方便
- 注解不是自己的类无法使用,维护较为复杂
建议(不是我说的):xml来管理bean,注解只负责完成属性的注入,在开发中要注意必须让注解生效
五、使用Java方式配置
JavaConfig之前是spring的子项目,在spring4之后变成了核心功能,完全不需要配置文件,交给Java文件来实现。获取对象时候需要使用AnnotationConfigApplicationContext
public class User{
private String name;
//get set toString等
}
@Configuration
//configration也会被spring容器托管
@ComponentScan("")
//扫描包
@import("xxx.class")
//引入配置文件,类似xml的引入
public class myConfig{//任意命名
@Bean
public User getUserBean(){
return newUser();
}
}
六、AOP
6.1、代理模式
spring实现AOP底层就是代理模式,代理模式可以使真实角色的业务操作更加纯粹,不用去关注公共业务,实现了业务的分工,在公共业务发生扩展的时候方便集中管理,但一个角色会有一个代理,代码量翻倍,开发效率变低(解决方案动态代理)。
-
静态代理
- 抽象角色-一般使用接口或者抽象类
- 真实角色-被代理的角色
- 代理角色-代理真实角色,代理后一般会完成一些附属操作
- 客户-访问代理对象的角色
-
动态代理-反射实现
- 角色与静态一样
- 代理类是静态生成的
- 实现分为两大类:基于接口(jdk动态代理)的和基于类(cglib)的
- javassist–jboss服务器
Proxy-代理:提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类
InvocationHandler(调用处理程序):每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法
6.2、动态代理实现机制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HRLn3Myy-1617276189564)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20210330110400079.png)]
InvocationHandler handler = new MyInvocationHandler(...);
Class<?> proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(),Foo.class);
Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).newInstance(handler);
//方法二
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class<?>[] {Foo.class},handler);
6.3、AOP实现
AOP(Aspect Oriented Programming)意为面向切面编程,是一种通过预编译方式和运行时期动态代理实现程序功能的同意维护的技术.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BQhTWIi0-1617276189573)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20210330154655808.png)]
AOP在Spring中的作用:提供声明式事务;允许用户自定义切面
- 横切关注点:跨越应用程序多个模块的功能或者方法,即与业务逻辑无关,但需要我们关注的部分,如日志,安全,事务等
- 切面(Aspect):横切关注点被模块化的特殊对象,即,一个类
- 通知(Advice):切面必须要完成的工作,即类中的方法
- 目标(Target):被通知对象
- 代理(Proxy):向目标应用对象通知后创建的对象
- 切入点(PointCut):切面通知,执行"地点"的定义
- 连接点(Joint Point):与切入点匹配的执行点
前置(方法前),后置(方法后),环绕(方法前后),异常(方法抛出异常),引介(方法增加属性)
6.3.1、spring的API接口
实现接口
在XML文件中配置AOP
<!--记得导入约束xmlns:aop-->
<aop:config>
<!--id切入点命名 expression表达式 -->
<aop:pointcut id="pointcut" expression="execution( * cn.yu.beans.*(..) )"/>
<!--通知-->
<aop:advisor advice-ref="log" pointcut-ref="point"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="point"/>
</aop:configa>
6.3.2、自定义类
<!--记得导入约束xmlns:aop-->
<aop:config>
<!--id切入点命名 expression表达式 -->
<aop:aspect ref="bean">
<!--切入点-->
<aop:pointcut id="pointcut" expression="execution( * cn.yu.beans.*(..) )"/>
<!--通知-->
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
</aop:aspect>
</aop:configa>
6.4、注解实现
@Aspect //标记切面
public class AnnotationProxy{
//方法执行前
@Before("exection(* com.yu.bean.*(..))")
public void before(){
System.out.println("....");
}
}
<!--开启注解支持-->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!--默认为false,修改为true之后使用cglib代理-->
七、事务
7.1、声明式事务
配置声明式事务
<bean id="transactionManager" class="org.springframework.jdbc.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--结合AOP进行事务织入-->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<!--结合AOP进行事务织入-->
<tx:attributes>
<!--事务传播方式,共七种,默认REQUIRED-->
<tx:methods name="*" propagation="REQUIRED"/>
<tx:methods name="search" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPoint" expression="execution( * cn.yu.beans.*(..) )"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>
</aop:config>