1.Maven项目导入依赖:导入webmvc会自动导入其他需要的依赖(推荐)
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
</dependencies>
2.ApplicationContext.xml(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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--bean就是java对象 , 由Spring创建和管理-->
</beans>
3.IOC容器
4.IOC创建对象的的几种方式
4.1有参数创建对象的几种方式
第一种:通过下标赋值
<!-- 第一种根据index参数下标设置 -->
<bean id="userT" class="com.qidian.pojo.UserT">
<!-- index指构造方法 , 下标从0开始 -->
<constructor-arg index="0" value="kuangshen2"/>
</bean>
第二种:通过类型创建
<!-- 第二种根据参数名字设置 -->
<bean id="userT" class="com.qidian.pojo.UserT">
<!-- name指参数名 -->
<constructor-arg name="name" value="kuangshen2"/>
</bean>
第三种:通过属性名创建
<!-- 第三种根据参数类型设置 -->
<bean id="userT" class="com.qidian.pojo.UserT">
<constructor-arg type="java.lang.String" value="kuangshen2"/>
</bean>
总结:在配置文件加载的时候,实例对象就被 创建了
5.spring的配置
5.1别名
举例:
<!--设置别名:在获取Bean的时候可以使用别名获取-->
<alias name="userT" alias="userNew"/>
5.2 Bean的配置
id:bean的唯一标识符,类似于我们创建的对象名
class:bean对象对应的全限定类名
name:别名,可以同时取多个别名
<!--bean就是java对象,由Spring创建和管理-->
<!--
id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
如果配置id,又配置了name,那么name是别名
name可以设置多个别名,可以用逗号,分号,空格隔开
如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;
class是bean的全限定名=包名+类名
-->
<bean id="hello" name="hello2 h2,h3;h4" class="com.qidian.pojo.Hello">
<property name="name" value="Spring"/>
</bean>
5.3import 的配置
一般用于团队开发,可以导入其他的beanx.xml,整合作用
<import resource="{path}/beans.xml"/>
6.DI依赖注入
6.1构造器注入
6.2set方式注入
依赖:bean对象的创建依赖容器;
注入:bean对象中的所有属性,由容器注入;
环境搭建:
Student类:
package com.qidian.pojo;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
// get和set略
public void show(){
System.out.println("name="+ name
+ ",address="+ address.getAddress()
+ ",books="
);
for (String book:books){
System.out.print("<<"+book+">>\t");
}
System.out.println("\n爱好:"+hobbys);
System.out.println("card:"+card);
System.out.println("games:"+games);
System.out.println("wife:"+wife);
System.out.println("info:"+info);
}
}
Address类:
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
beans.xml
常量注入:
<bean id="student" class="com.qidian.pojo.Student">
<property name="name" value="小明"/>
</bean>
Bean注入: ref是一个引用
<bean id="addr" class="com.qidian.pojo.Address">
<property name="address" value="重庆"/>
</bean>
<bean id="student" class="com.kuang.pojo.Student">
<property name="name" value="小明"/>
<property name="address" ref="addr"/>
</bean>
数组注入:
<bean id="student" class="com.qidian.pojo.Student">
<property name="name" value="小明"/>
<property name="address" ref="addr"/>
<property name="books">
<array>
<value>西游记</value>
<value>红楼梦</value>
<value>水浒传</value>
</array>
</property>
</bean>
list注入:
<property name="hobbys">
<list>
<value>听歌</value>
<value>看电影</value>
<value>爬山</value>
</list>
</property>
map注入:
<property name="card">
<map>
<entry key="中国邮政" value="456456456465456"/>
<entry key="建设" value="1456682255511"/>
</map>
</property>
set注入:
<property name="games">
<set>
<value>LOL</value>
<value>BOB</value>
<value>COC</value>
</set>
</property>
Null注入:
<property name="wife"><null/></property>
Properties注入:
<property name="info">
<props>
<prop key="学号">20190604</prop>
<prop key="性别">男</prop>
<prop key="姓名">小明</prop>
</props>
</property>
6.3其他方式注入
P命令注入
导入约束 : xmlns:p="http://www.springframework.org/schema/p"
<!--P(属性: properties)命名空间 , 属性依然要设置set方法-->
<bean id="user" class="com.qidian.pojo.User" p:name="大锤" p:age="18"/>
C命令注入:!!!!需要有对应的构造器
导入约束 : xmlns:c="http://www.springframework.org/schema/c"
<!--C(构造: Constructor)命名空间 , 属性依然要设置set方法-->
<bean id="user" class="com.qidian.pojo.User" c:name="大锤" c:age="18"/>
注意:P命名空间和C命名空间不能直接使用,需要导入对应约束
6.4Bean对象的作用域
1.singleton:默认是单例,所有请求共享一个实力对象
<bean id="userServiceImpl" class="com.qidian.service.UserServiceImpl" scope="singleton">
2.prototype:原型模式,表示一个bean定义对应多个对象实例。从容器中get的时候,每次都会创建一个新的对象。
<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/>
或者
<bean id="account" class="com.foo.DefaultAccount" singleton="false"/>
3.request和session和application:在web项目中使用,分别对应一次请求,一次会话和应用程序。
7.Bean的自动装配
自动装配:意思是spring会在应用上下文中为某个bean寻找其依赖的bean。
7.1byName
<bean id="user" class="com.qidian.pojo.User" autowire="byName">
<property name="str" value="kakaxi"/>
</bean>
7.2byType
!!使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。
<bean id="dog" class="com.qidian.pojo.Dog"/>
<bean id="cat" class="com.qidian.pojo.Cat"/>
<bean id="cat2" class="com.qidian.pojo.Cat"/>
<bean id="user" class="com.qidian.pojo.User" autowire="byType">
<property name="str" value="qinjiang"/>
</bean>
-
测试,报错:NoUniqueBeanDefinitionException,将cat的bean名称改掉!测试!因为是按类型装配,所以并不会报异常,也不影响最后的结果。甚至将id属性去掉,也不影响结果。
7.3注解实现自动装配
引入context文件头:
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
开启属性注解:
<context:annotation-config/>
7.3.1 @Autowired
- @Autowired是按类型自动转配的,不支持id匹配。
- 需要导入 spring-aop的包!
测试:去掉get和set方法
public class User {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String str;
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
public String getStr() {
return str;
}
}
配置文件:
<context:annotation-config/>
<bean id="dog" class="com.qidian.pojo.Dog"/>
<bean id="cat" class="com.qidian.pojo.Cat"/>
<bean id="user" class="com.qidian.pojo.User"/>
测试结果成功;
tips:
@Autowired(required=false) 说明: false,对象可以为null;true,对象必须存对象,不能为null。
7.3.2Qualifier:在autowired的基础上,加上qualifier还可以根据名字实现自动专配;
<bean id="dog1" class="com.qidian.pojo.Dog"/>
<bean id="dog2" class="com.qidian.pojo.Dog"/>
<bean id="cat1" class="com.qidian.pojo.Cat"/>
<bean id="cat2" class="com.qidian.pojo.Cat"/>
7.3.3@Resource
- @Resource如有指定的name属性,先按该属性进行byName方式查找装配;
- 其次再进行默认的byName方式进行装配;
- 如果以上都不成功,则按byType的方式自动装配。
- 都不成功,则报异常。
8.使用注解开发
1:使用注解开发,要导包(aop),配置文件还要导入contect约束
<?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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
@Component一般放在类上面,表示组件
2.衍生注解
dao:@Repository
service:@service
controller:@Controller
都是代表将类放到容器中,自动装配
3.作用域:@Scope
9.使用java类实现配置spring
10.动态代理
几种实现动态代理的方式
- 基于接口----JDK实现,
- 基于类:cglib
- java字节码实现,javassist
代理类实现代码:
public class ProxyInvocationHandler implements InvocationHandler {
public Object target;
public void setTarget(Object target) {
this.target = target;
}
// 获取动态代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(target,args);
}
}
测试:动态代理的好处
- 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
- 公共的业务由代理来完成 . 实现了业务的分工 ,
- 公共业务发生扩展时变得更加集中和方便 .
- 一个动态代理 , 一般代理某一类业务
- 一个动态代理可以代理多个类,代理的是接口!
11.AOP
什么是AOP:AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
实现aop
导包:
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
三种方式是实现aop
1:Spring API实现
增强类:
public class Log implements MethodBeforeAdvice {
//method : 要执行的目标对象的方法
//objects : 被调用的方法的参数
//Object : 目标对象
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println( o.getClass().getName() + "的" + method.getName() + "方法被执行了");
}
}
然后在spring文件中注册实现aop切入实现
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注册bean-->
<bean id="userService" class="com.qidian.service.UserServiceImpl"/>
<bean id="log" class="com.qiidan.log.Log"/>
<!--aop的配置-->
<aop:config>
<!--切入点 expression:表达式匹配要执行的方法-->
<aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
<!--执行环绕; advice-ref执行方法 . pointcut-ref切入点-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
</beans>
2:自定义类实现aop
public class DiyPointcut {
public void before(){
System.out.println("---------方法执行前---------");
}
public void after(){
System.out.println("---------方法执行后---------");
}
}
去sprng中配置
<!--第二种方式自定义实现-->
<!--注册bean-->
<bean id="diy" class="com.qidian.config.DiyPointcut"/>
<!--aop的配置-->
<aop:config>
<!--第二种方式:使用AOP的标签实现-->
<aop:aspect ref="diy">
<aop:pointcut id="diyPonitcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
<aop:before pointcut-ref="diyPonitcut" method="before"/>
<aop:after pointcut-ref="diyPonitcut" method="after"/>
</aop:aspect>
</aop:config>
3:使用注解实现
第一步:b编写一个注解实现的增强类
package com.qidian.config;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class AnnotationPointcut {
@Before("execution(* com.qidian.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("---------方法执行前---------");
}
@After("execution(* com.qidian.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("---------方法执行后---------");
}
@Around("execution(* com.qidian.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint jp) throws Throwable {
System.out.println("环绕前");
System.out.println("签名:"+jp.getSignature());
//执行目标方法proceed
Object proceed = jp.proceed();
System.out.println("环绕后");
System.out.println(proceed);
}
}
第二部:配置文件中配置
<!--第三种方式:注解实现-->
<bean id="annotationPointcut" class="com.qidian.config.AnnotationPointcut"/>
<aop:aspectj-autoproxy/>
aop:aspectj-autoproxy:说明
1.通过aop命名空间的<aop:aspectj-autoproxy />声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,织入切面。当然,spring 在内部依旧采用AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被<aop:aspectj-autoproxy />隐藏起来了
2.<aop:aspectj-autoproxy />有一个proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class="true"/>时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理。

被折叠的 条评论
为什么被折叠?



