Spring基础学习
一、IOC
1、主类配置
public void testOrders() { //1、加载spring配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); //2、获取配置创建对象 Book book = context.getBean("orders",Orders.class); System.out.println(book); book.testDemo(); }
2、在spring配置文件配置对象创建,配置属性的注入
-
使用无参构造进行注入
<bean id="xxx" class="com.xxx.xxx"> <property name="xxx" value="xxx"></property> <property name="xxx" value="xxx"></property> .... </bean>
-
使用有参构造进行注入
<bean id="xxx" class="com.xxx.xxx"> <constructor-arg name="xxx" value="xxx"></constructor-arg> <constructor-arg name="xxx" value="xxx"></constructor-arg> .... </bean>
3、xml注入其他类型属性
-
字面量
(1)null(空值)
<bean id="xxx" class="com.xxx.xxx"> <property name="xxx" ><null/></property> </bean>
(2)属性值包含特殊符号
<bean id="xxx" class="com.xxx.xxx"> //1、把特殊符号进行转义 <property name="xxx" values="<><<南京>>"></property> //2、把带特殊符号的内容写到带CDATA中 <property name="xxx" > <value><![CDATA[<<南京>>]]></value> </property> </bean>
-
注入外部bean
(1)创建两个类service类和dao类
(2)在service调用dao里面的方法
-
注入属性-内部bean
<bean id="emp" class="com.xxx.xxx"> //1、设置两个普通属性 emp:员工 dept:部门 <property name="ename" values="lucy"></property> <property name="gender" values="女"></property> //2、设置对象类型属性 <property name="dept" > <bean id="dept" class="com.xxx.xxx"> <property name="dname" value="安保部"></property> </bean> </property> </bean>
-
级联赋值
(1)第一种写法
<bean id="emp" class="com.xxx.xxx"> //1、设置两个普通属性 emp:员工 dept:部门 <property name="ename" values="lucy"></property> <property name="gender" values="女"></property> //级联赋值 <property name="dept" ref="dept"></property> </bean> <bean id="dept" class="com.xxx.xxx"> <property name="dname" value="财务部"></property> </bean>
(2)第二种写法 //需生成get方法
<bean id="emp" class="com.xxx.xxx"> //1、设置两个普通属性 emp:员工 dept:部门 <property name="ename" values="lucy"></property> <property name="gender" values="女"></property> //级联赋值 <property name="dept" ref="dept"></property> <property name="dept.dname" value="技术部"></property> </bean> <bean id="dept" class="com.xxx.xxx"> <property name="dname" value="财务部"></property> </bean>
4、xml注入集合类型属性
//创建学生对象 public class stu { //1、数组类型属性 private String[] courses; //2、list集合类型属性 private List<String> list; //3、Map集合类型属性 private Map<String> map; //4、set类型属性 private Set<String> set; public void setCourses(String[] courses){ this.courses = courses; } }
//在spring配置文件中配置 <bean id="stu" class="com.xxx.xxx"> //1、数组类型属性注入 <property name="courses"> <array> <value>java</value> <value>数据库</value> </array> </property> //2、list类型属性注入 <property name="courses"> <list> <value>sql</value> <value>数据库</value> </list> </property> //3、map类型属性注入 <property name="courses"> <map> <entry key="JAVA" value="java"></entry> <entry key="JAVA" value="java"></entry> </map> </property> //4、set类型属性注入 <property name="courses"> <set> <value></value> <value></value> </set> </property> </bean>
在集合里设置对象类型
//学生所学多门课程 private List<Course> courseList; publice void setCoureList(List<Course> couseList) { this.courseList = courseList; }
//注入list集合类型,值是对象 <bean id="stu" class="com.xxx.xxx"> <property name="courseList"> <list> <ref bean="course1"></ref> <ref bean="course2"></ref> </list> </property> </bean> //创建多个cuorse对象 <bean id="course1" class="com.xxx.xxx"> <property name="cname" value="Sprint5"></property> </bean> <bean id="course2" class="com.xxx.xxx"> <property name="cname" value="Sprintboot"></property> </bean>
把集合注入的部分提取出来
(1)在spring配置文件中引入名称空间util
-
//1、提取list集合类型属性注入 <util:list id="booklist"> <value>1</value> <value>2</value> <value>3</value> </util:list> //2、提取list集合类型属性注入的使用 <bean id="book" class="com.xxx.xxx"> <property name="list" ref="booklist"></property> </bean>
4、设置单实例、多实例
(1)在spring配置文件bean标签中属性(scope)用于设置单实例还是多实例
(2)scope属性值:
默认值:singleton,表示是单实例对象
prototype:表示是多实例对象
5、bean的生命周期
-
通过构造器创建bean实例(无参构造)
-
为bean的属性设置值和对其他bean引用(调用set方法)
-
调用bean的初始化的方法(需要进行配置初始化的方法)
-
对象获取到了
-
当容器关闭时,调用bean的销毁方法(需进行配置销毁方法)context.close()
6、自动装配
bean标签属性Autowire,配置自动装配
autowire属性常用的两个值:1、byName:根据属性名称注入,注入值bean的id值和属性名称一样 2、byType:根据属性类型注入
7、Bean管理注解方式
1、spring针对Bean管理中创建对象提供注解
(1)@Component
(2)@Service
(3)@Controller
(4)@Repository
功能是一样的,都可以用来创建bean实例,用在不同层
2、基于注解方式实现对象创建
//①引入依赖 //②开启组件扫描 //③创建类,在类上面添加创建对象注解 //开启注解扫描 1、如果扫描多个包,用逗号隔开
2、扫描包上层目录
<context:component-scan base-package="com.xxx"></context:component-scan> //示例1 use-default-filters="false"表示现在不使用默认filter,自己配置filter context:include-filter,设置扫描哪些内容 <context:component-scan base-package="com.xxx" use-default-filters="false"> <context:include-filter type="annotaion" expression="org.springframework.stereotype.Controller"/>//只扫描带注解Controller的类 </context:component-scan> //示例二 <context:componeexnt-scan base-package="com.xxx"> <context:exclude-filter type="annotaion" expression="org.springframework.stereotype.Controller"/>//不扫描带Controller的注解类 </context:component-scan>
3、基于注解方式实现属性注入
-
@Autowired:根据属性类型进行自动装配
-
@Qualifier:根据属性名称进行注入
-
@Resource:可以根据类型注入,也可以根据名称注入
-
@Value:注入普通类型属性,如下:
@Value(value = "abc") private String name; //name=="abc"
4、完全注解开发
(1)创建配置类,替代xml配置文件,config包
@Configuration //作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"com.xxx"}) //实现组件扫描
//1、加载spring配置文件 ApplicationContext context = new AnnotatuonConfigApplicationContext(xxx.class);
二、AOP
基本概念: 不通过修改源代码方式添加新的功能的过程
1、AOP底层使用动态代理,有两种情况
(1)有接口情况,使用JDK动态代理
创建接口实现类代理对象,增强类的方法
(2)无接口情况,使用CGLIB动态代理
创建当前类子类的代理对象
AOP(JDK动态代理)
1、使用jdk动态代理,使用Proxy类里面的方法创建代理对象
(1)调用newProxyInstance方法
三个参数:
-
ClassLoader loader:类加载器
-
类<?>[] interfaces:增强方法所在的类,这个类实现的接口,支持多个接口
-
InvocationHandler h:实现这个接口InvocationHandler,创建代理对象,写增强的方法
2、Spring框架一般都是基于AspectJ实现AOP操作
AspectJ:不是spring组成部分,是独立的AOP框架,一般把AspectJ和Spring框架一起使用,进行Aop操作
相同切入点抽取
@Pointcut(value="execution(* com.xxx.xxxx.add(..))") public void pointdemo(){ } //前置通知 @Before(value = "pointdemo()")
AOP操作(注解方式)
-
导入依赖
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency>
-
创建类,在类中定义方法
public class User { public void add() { System.out.println("add.........."); } }
-
创建增强类(编写增强的逻辑)
@Component @Aspect public class UserPorxy { //前置通知 @Before(value = "execution(* com.dong.spring5.aopanno.User.add())") public void before() { System.out.println("before........"); } }
-
进行通知的配置
(1)在spring配置文件中,开启注解的扫描
(2)使用注解创建User和UserProxy对象
(3)在增强类上添加注解@Aspect
(4)在spring配置文件中开启生成代理对象
<?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.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:component-scan base-package="com.dong.spring5"></context:component-scan> <!--开启Aspect生成代理对象--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
通知类型:
//1.前置通知 @Before(value = "execution(* com.dong.spring5.aopanno.User.add())") //2.后置通知(返回通知) @AfterReturningtion(value = "execution(* com.dong.spring5.aopanno.User.add())") //3.最终通知 @After(value = "execution(* com.dong.spring5.aopanno.User.add())") //4.异常通知 @AfterThrowing(value = "execution(* com.dong.spring5.aopanno.User.add())") //5.环绕通知 @Around(value = "execution(* com.dong.spring5.aopanno.User.add())")