Spring5

it2025-02-01  11

总结:

1、spring就是一个轻量级的控制反转(IOC)和面相切面(AOP)编程的框架 2、IOC,总结一句话就是对象由spring来创建、管理、装配,其实现方法是依赖注入 3、实现IOC的三种方式: application.xml配置文件 注解方式:<context:annotation-config/> java的Configuration(完全舍弃xml文件) 最佳搭配方式:xml负责管理bean,注解负责属性的自动装配 4、@Autowired 是spring的注解 自动装配、@Resource 是java的注解 自动装配 5、AOP切面实现方式:标签<aop> 方式一:Spring内置的AOP接口实现before、after两个接口的类,将类配置在切面中 方式二:自定义类,在类中自定义before、after方法,配置在切面上 方式三:在自定义类上加@Aspect,定义这是一个切面,在类中的方法上加注解@Before、@After定义这些方法是切面里面的方法 6、声明式事务:标签<tx> 配置<tx>事务,声明方法将事务织入切面

定义:spring就是一个轻量级的控制反转(IOC)和面相切面(AOP)编程的框架

IOC(Sping核心)

Inversion of controller 控制反转

控制反转是一种通过描述(xml或注解)并通过第三方去生产或获取特定对象的方式。

在spring中实现控制反转的是IOC容器,其实现方法是依赖注入(Dependency Injection DI)

控制:谁来控制对象的创建,传统应用程序的对象是由程序本身创建的,使用spring后是由spring创建的

反转:程序本身不创建对象,而是被动的接收对象

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml")

注:当加载了xml文件获取到ioc容器对象context的时候,容器内就已经生成了各个对象

依赖注入:就是利用set方法注入的 (property属性的值由对象的set方法注入)

IOC是一种编程思想,由主动的编程编程被动的接受

所谓的IOC,总结一句话就是对象由spring来创建、管理、装配

实现IOC的三种方式:

application.xml配置文件注解方式java的Configuration(完全舍弃xml文件) 最佳搭配方式:xml负责管理bean,注解负责属性的自动装配

1、xml配置文件实现IOC

使用ClassPathXmlApplicationContext对象加载xml文件获取IOC容器

public class UserController { public static void main(String[] args) { //当xml文件被加载之后,所有管理的对象就已经初始化了 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserServiceImpl bean = (UserServiceImpl)context.getBean("userServiceImpl"); System.out.println(bean.getUser()); } }

属性通过set赋值

<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"> <!--使用spring来创建对象--> <bean id="hello" class="pojo.Hello"> <property name="str" value="wanghan"/> </bean> </beans>

属性通过构造方法赋值

<bean id="hello" class="pojo.Hello"> <constructor-arg name="name" value="wnaghan"/> </bean>

依赖注入

依赖:bean对象的创建依赖于容器注入:bean对象中所有属性,由容器来注入

各种属性配置方式:普通类型、数组、map、list、properties、set等数据类型

<bean id="moreComplexObject" class="example.ComplexObject"> <!-- properties类型数据 --> <property name="adminEmails"> <props> <prop key="administrator">administrator@example.org</prop> <prop key="support">support@example.org</prop> <prop key="development">development@example.org</prop> </props> </property> <!-- list --> <property name="someList"> <list> <value>a list element followed by a reference</value> <ref bean="myDataSource" /> </list> </property> <!-- map --> <property name="someMap"> <map> <entry key="an entry" value="just some string"/> <entry key ="a ref" value-ref="myDataSource"/> </map> </property> <!-- set --> <property name="someSet"> <set> <value>just some string</value> <ref bean="myDataSource" /> </set> </property> <!-- 数组 --> <property name="books"> <array> <value>三国演义</value> <value>水浒传</value> </array> </property> </bean>

p命名空间 (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="john-classic" class="com.example.Person"> <property name="name" value="John Doe"/> <property name="spouse" ref="jane"/> </bean> <bean name="john-modern" class="com.example.Person" p:name="John Doe" p:spouse-ref="jane"/> <bean name="jane" class="com.example.Person"> <property name="name" value="Jane Doe"/> </bean> </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>

注意:p命名空间和c命名空间都不能直接使用,需要导入c和p得约束文件

xmlns:c="http://www.springframework.org/schema/p xmlns:c="http://www.springframework.org/schema/c

bean作用域

singleton 单例模式(spring默认机制):只生成一个对象prototype 原型模式:生成多个对象其余得request、session、application只有在web开发中才能使用到

bean的自动装配

自动装配是Spring满足bean依赖的一种方式spring会在上下文中自动寻找,并自动给bean装配属性

byName

byType

2、注解方式实现IOC

使用注解的前提

导入AOP的依赖包

在application.xml中导入约束文件

开启注解和组件包扫描

<--开启注解--> <context:annotation-config/> <--使用@Component将类配置到IOC容器中--> <context:component-scan base-package="com.kayak.pojo"/>

注解说明:

@Autowired 是spring的注解 自动装配 通过byType方式实现,如果类型不唯一,则需要通过 @Qualifier来指定id名称来实现@Resource 是java的注解 自动装配 通过byname方式,如果名字找不到,则通过bytype方式实现@Component:组件,放在类上,说明这个类被spring管理了,就是bean!需要在xml中配置组件扫描包的路径 <context:component-scan base-package="pojo"/> @Scop:作用域@Scop(“singleton”)或者prototype @Autowired @Qualifier(value = "dog") //可以配置不同的id名称 private Dog dog; @Resource(name = "cat") //可以配置不同的id名称 private Cat cat; @Component public class Dog { public void shout(){ System.out.println("汪"); } }

3、使用java配置spring实现IOC

使用AnnotationConfigApplicationContext对象加载xml文件获取IOC容器 我们现在 要完全不使用xml配置了,全权交给java来配置

@Configuration @Import(MyConfiguration2.class) //合并另一个配置类 public class MyConfiguration { @Bean public StringStore stringStore() { return new StringStore(); } @Bean public IntegerStore integerStore() { return new IntegerStore(); } } public class MyTest { public static void main(String[] args) { //使用AnnotationConfigApplicationContext对象加载xml文件获取IOC容器 ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); People people = context.getBean("people", People.class); people.getCat().shout(); people.getDog().shout(); } }

代理模式

springAOP的底层就是代理模式

代理模式的分类:

1、静态代理

代理模式的好处:

可以使真实角色的操作更加纯粹,不用去关注一些公共业务公共业务交给代理角色公共业务发生拓展时,方便集中管理(可以在不改变原有代码的基础上,增加新的业务)

静态代理模式的缺点: 一种真实角色就会产生一种代理角色,代码量会翻倍,静态代理只能代理一个接口 (例如房屋中介,只代理房东租房,不做婚介)

代码步骤:

接口(租房)

//租房接口 public interface Rent { void rent(); }

真实角色(房东)

public class Host implements Rent { public void rent() { System.out.println("我是房东,我要出租房子"); } }

代理角色(中介)

public class Proxy implements Rent { //房东Host实现租房的接口 //租房的接口 private Rent rent; public Proxy() { } public Proxy(Rent rent) { this.rent = rent; } public void rent() { rent.rent(); } //属于公共事务,交由代理对象办理,公共事务变更时,代码更易于管理 public void payServicefee(){ System.out.println("交物业费"); } }

客户访问(客户)

//客户租房 public class Client { public static void main(String[] args) { //host房东 Host host = new Host(); //找代理对象,代理对象有参构造传入房东,房东出租房子 Proxy proxy = new Proxy(host); proxy.rent(); //执行代理对象中的公共事务方法 proxy.payServicefee(); } }

代理模式的理解

2、动态代理(反射实现)

动态代理和静态代理角色一样动态代理的代理类是动态生成的动态代理分为两大类: 1、基于接口的动态代理—JDK的动态代理 2、基于类的动态代理—cglib 3、java字节码实现 : javasist

需要了解两个类:Proxy代理、InvocationHandler调用处理

动态代理理解: 1、动态代理实现InvocationHandler接口 2、利用Proxy里面的静态方法 Proxy.newProxyInstance()得到代理实例 3、实现InvocationHandler接口中的方法,method.invoke(),执行代理接口中的方法

//自定义动态代理 public class ProxyInvocationHandler implements InvocationHandler { //定义接口 private 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 { //method指代理接口的方法 Object result = method.invoke(target, args);//执行调用代理接口的方法 payServicefee();//执行拓展的公共事务 return result; } //拓展的公共事务 public void payServicefee() { System.out.println("交物业费"); } } public class Client { public static void main(String[] args) { //获取动态代理工具 ProxyInvocationHandler pih = new ProxyInvocationHandler(); //target属性注入要代理的对象 pih.setTarget(new Host()); //获取代理对象 Rent proxy = (Rent) pih.getProxy(); //代理对象执行方法 proxy.rent(); } }

AOP

方式一:spring的API接口

@Component public class Log implements MethodBeforeAdvice { // method:要执行的目标对象的方法 //args:参数 //target:目标对象 public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了"); } } @Component public class AfterLog implements AfterReturningAdvice { //oreturnValue:返回值 public void afterReturning(Object turnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("执行了"+method.getName()+"返回结果为:"+turnValue); } } <?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" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.kuang"/> <context:annotation-config/> <!--配置AOP:需要导入aop约束--> <aop:config> <!--切入点;expression--> <aop:pointcut id="myPointCut" expression="execution(* com.kuang.service.*.*(..))"/> <!--执行环绕--> <aop:advisor advice-ref="log" pointcut-ref="myPointCut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="myPointCut"/> </aop:config> </beans>

方式二:自定义类实现aop(切面定义)

@Component public class MyAspect { public void before(){ System.out.println("方法执行前"); } public void after() { System.out.println("方法执行后"); } } <?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" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.kuang"/> <context:annotation-config/> <aop:config> <aop:aspect ref="myAspect"> <aop:pointcut id="diy" expression="execution(* com.kuang.service.*.*(..))"/> <aop:before method="before" pointcut-ref="diy"/> <aop:after method="after" pointcut-ref="diy"/> </aop:aspect> </aop:config> </beans>

方式三:注解实现aop

@Component @Aspect public class AnnotationPointCut { @Before("execution(* com.kuang.service.*.*(..))") public void before(){ System.out.println("方法执行前"); } @After("execution(* com.kuang.service.*.*(..))") public void after(){ System.out.println("方法执行后"); } } <?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" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.kuang"/> <context:annotation-config/> <!--开启aop注解--> <aop:aspectj-autoproxy/> </beans>

整合Mybatis

导spring-jdbc包

<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.9.RELEASE</version> </dependency>

spring整合mybatis,就是将数据源、sqlSessionFactory、sqlSession交由IOC容器管理,再由mapper接口的实现类装配sqlsession

<?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"> <!--将数据源交给IOC--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://192.168.168.132:3306/test"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <!--将sqlSessionFactory交给IOC,并将数据源装配给sqlSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!--可以引入mybatis-config原始的配置文件,其他的配置属性可以生效--> <property name="configLocation" value="classpath:mybatis-config.xml"/> <!--设置mapper的引入路径,也可以在mybatis-config.xml中配置,然后由configLocation引入--> <property name="mapperLocations" value="classpath:mapper/*.xml"/> </bean> <!--将sqlsession交给IOC容器,Spring框架中由sqlSessionTemplate代替sqlSession--> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> <!--mapper接口的实现类,并用set方法,将sqlSessionTemplate装配到实现类中--> <bean id="userMapper" class="mapper.UserMapperImpl"> <property name="sqlSession" ref="sqlSession"/> </bean> </beans> public class UserMapperImpl implements UserMapper { private SqlSessionTemplate sqlSession; public void setSqlSession(SqlSessionTemplate sqlSession) { this.sqlSession = sqlSession; } public List<User> query() { UserMapper mapper = sqlSession.getMapper(UserMapper.class); return mapper.query(); } } public class MybatisTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); UserMapper mapper = context.getBean("userMapper", UserMapper.class); for (User user : mapper.query()) { System.out.println(user); } } }

声明式事务

要么都成功,要么都失败事务在开发中十分重要,涉及到数据的一致性,不能马虎!确保完整性和一致性

事务的ACID原则

原子性 :是指事务的所有操作在数据库中要么全部正确反映出来,要么全部不反映一致性:必须是使数据库从一个一致性状态变到另一个一致性状态隔离性:一个事务内部的操作及使用的数据对并发的其他事务是隔离的持久性:事务一旦提交,对数据库的修改就是永远的

sring中事务管理:

声明式事务编程式事务 <!--结合AOP实现事务的织入--> <!--配置声明式事务--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!--给哪些方法配置事务--> <!--配置事务的传播性:new propagation--> <tx:method name="*" propagation="REQUIRED"/> <tx:method name="query" read-only="false"/> </tx:attributes> </tx:advice> <!--配置事务切入--> <aop:config> <aop:pointcut id="myPoint" expression="execution(* mapper.UserMapperImpl.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="myPoint"/> </aop:config>
最新回复(0)