Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器
Spring框架是一个分层架构,由七个模块组成。构建在核心容器上(Spring Core),核心容器定义了创建,配置和管理Bean的方式。
每个模块的功能如下:
控制反转(Inversion Of Control)IOC是一种设计思想,依赖注入(Dependency Injection)DI是一种方法
程序创建对象==>容器创建对象
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建并组织对象存入IOC容器中,当程序需要使用对象时从容器中取出对象即可
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.5</version> </dependency>
public class Hello { private String name; public Hello(){ System.out.println("调用无参构造"); } public String getName(){ return name; } public void setName(String name){ this.name=name; } public void show(){ System.out.println("Hello,"+name); } }
<?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 id="hello" class="com.deng.Entity.Hello"> <property name="name" value="Spring"></property> </bean> </beans>
public void test1(){ //解析beans.xml配置文件,生成管理bean的对象 ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml"); //根据bean的id获取bean对象 Hello hello=(Hello)context.getBean("hello"); hello.show(); }
<bean id="hello" class="com.deng.Entity.Hello">
<!-- name指参数名 -->
<constructor-arg name="name" value="Spring"/>
</bean>
要求被注入的属性必须由set方法才能注入
<bean id="hello" class="com.deng.Entity.Hello"> <property name="name" value="Spring"></property> </bean>
<bean id="address" class="com.deng.Entity.Address"> <property name="address" value="zhejianghangzhou"></property> </bean> <bean id="hello" class="com.deng.Entity.Hello"> <property name="name" value="Spring"></property> <property name="address" ref="address"></property> </bean>
<property name="books"> <array> <value>西游记</value> <value>红楼梦</value> <value>水浒传</value> </array> </property>
<property name="hobbys"> <list> <value>西游记</value> <value>红楼梦</value> <value>水浒传</value> </list>
</property>
<property name="card"> <map> <entry key="中国邮政" value="456456456465456"/> <entry key="建设" value="1456682255511"/> </map> </property>
<property name="games"> <set> <value>LOL</value> <value>BOB</value> <value>COC</value> </set> </property>
<property name="wife"><null/></property>
<property name="info"> <props> <prop key="学号">20190604</prop> <prop key="性别">男</prop> <prop key="姓名">小明</prop> </props> </property>
需要在头文件导入约束文件
<beans xmlns:p="http://www.springframework.org/schema/p"> <bean id="hello" class="com.deng.Entity.Hello" p:name="dwx"></bean> </beans>
需要在头文件导入约束文件,且必须要有有参构造函数才能使用
<beans xmlns:c="http://www.springframework.org/schema/c"> <bean id="hello" class="com.deng.Entity.Hello" c:name="dwx"></bean> </beans>
Bean就是IOC容器初始化,装配和管理的对象,有4种作用域:
bean的作用域为singleton时,IOC容器中只会存在一个共享的Bean实例,对于所有的bean请求,id与该bean相同就会返回同一实例。
在创建容器时就自动创建了一个bean对象,无论是否使用都存在。
singleton是bean的默认作用域,xml中定义如下
<bean id="hello" class="com.deng.Entity.Hello" scope="singleton"></bean>
prototype作用域的bean会导致每次对该bean对象请求(将该bean注入到另一个bean中,或者调用getBean()方法)时都会创建一个新的实例。在创建容器时,bean并没有实例化,而是在需要获取bean对象时才会去创建一个对象,并且每次获取的对象都不是同一对象。在xml中的定义如下
当bean的作用域为request时,表示每一个http请求都会有各自的bean实例,仅在基于web的SpringApplicationContext里有效。当处理请求结束后,request的作用域的bean实例将被销毁,在xml的定义如下
<bean id="hello" class="com.deng.Entity.Hello" scope="request"></bean>
bean的作用域为session,表示一个Http Session对应一个bean实例,仅在基于web的SpringApplicationContext里有效。Http Session结束后,bean也会被销毁
Spring会在应用上下文中为某个bean寻找其依赖的bean
bean的三种装配机制:
实现自动装配的两个操作:
3个实体类
//猫 public class Cat { public void shout(){ System.out.println("miaomiaomiao!!!"); } } //狗 public class Dog { public void shout(){ System.out.println("wangwangwang!!!"); } } //人 @Data public class User { private Cat cat; private Dog dog; private String name; }
编写配置文件
<?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 id="cat" class="com.deng.Entity.Cat"></bean> <bean id="dog" class="com.deng.Entity.Dog"></bean> <bean id="user" class="com.deng.Entity.User"> <property name="cat" ref="cat"></property> <property name="dog" ref="dog"></property> <property name="name" value="dwx"></property> </bean> </beans>
修改bean的参数配置,增加属性autowired="byName"
<bean id="cat" class="com.deng.Entity.Cat"></bean> <bean id="dog" class="com.deng.Entity.Dog"></bean> <bean id="user" class="com.deng.Entity.User" autowire="byName"> <property name="name" value="dwx"></property> </bean>
使用autowired byName属性时步骤:
按类型自动配置xml
使用autowire byType要确保同一类型的对象在Spring容器中唯一,如果不唯一就会抛出异常
<bean id="cat985" class="com.deng.Entity.Cat"></bean> <bean id="dog211" class="com.deng.Entity.Dog"></bean> <bean id="user" class="com.deng.Entity.User" autowire="byType"> <property name="name" value="dwx"></property> </bean>
首先要在xml文件中引入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></context:annotation-config>
public class User { @Autowired private Cat Cat; @Autowired private Dog dog; private String name; }
不需要set方法也可
@Autowired(required=false)//表示允许对象为null
public class User { @Autowired @Qualifier(value = "cat") private Cat Cat; @Autowired private Dog dog; private String name; }
@Data public class User { @Resource(name = "cat") private Cat cat; @Autowired private Dog dog; private String name; }
导入spring-aop注解,并在配置文件中引入context约束
在配置文件配置扫描哪些表下的注解
<?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 "> <context:component-scan base-package="com.deng.Entity"></context:component-scan> </beans>
在该包下的类增加注解@Component
@Component("user") public class User { public String name="dwx"; }
测试
public void test1() { ApplicationContext context=new ClassPathXmlApplicationContext("beans1.xml"); User user=(User) context.getBean("user"); System.out.println(user.name); }
@Component("user")
// 相当于配置文件中,<bean id="user" class="com.deng.Entity.User"/>
public class User {
@Value("dwx")
//相当于配置文件中<property name="name" value="dwx">
public String name;
}
@Component public class User { public String name; @Value("dwx") public void setName(String name) { this.name = name; } }
这些注解都是表示将对应的类交给spring管理
@Component @Scope("prototype") public class User { public String name; @Value("dwx") public void setName(String name) { this.name = name; } }
实体类
@Data public class Cat { private String name; }
编写Config配置类
@Configuration//表示这是一个配置类 public class MyConfig { @Bean//通过该方法注册一个bean,bean类型就是返回值,id就是方法名 public Cat cat(){ Cat cat=new Cat(); //注入值 cat.setName("jiafeimao"); return cat; } }
测试
public void test1() { //根据配置类创建applicationContext来管理bean对象 ApplicationContext context=new AnnotationConfigApplicationContext(MyConfig.class); //获取bean对象 Cat cat=(Cat)context.getBean("cat"); System.out.println(cat.getName()); }
导入其他配置类使用
@Import(MyConfig2.class)
代理就是在不改变原来的代码的情况下,对原有的功能进行增强
代理一个角色
//抽象角色:租房 public interface Rent { public void rent(); }
//中介 public class StaticProxy { private Host host; public StaticProxy(Host host){ this.host=host; } //租房 public void rent(){ seeHouse(); host.rent(); fare(); } //看房 public void seeHouse(){ System.out.println("看看房子"); } //收中介费 public void fare(){ System.out.println("收取中介费"); } }
//客户端 public class Client { public static void main(String[] args) { Host host=new Host(); StaticProxy staticProxy=new StaticProxy(host); staticProxy.rent(); } }
代理一类角色,动态代理的代理类是动态生成的,静态代理的代理类是提前写好的,需要了解接口InvocationHandler和类Proxy
InvocationHandler里的invoke()方法:调用处理程序
Proxy里的静态方法newProxyInstance()方法:创建代理实例
public class DtProxy implements InvocationHandler { private Rent rent; public void setRent(Rent rent){ this.rent=rent; } //生成代理类,第二个参数 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this); } //处理代理实例上的方法并将结果返回 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { seeHouse(); Object result=method.invoke(rent,args); fare(); return result; } //看房 public void seeHouse(){ System.out.println("带房客看房"); } //收中介费 public void fare(){ System.out.println("收中介费"); } }
//客户端 public class Client { public static void main(String[] args) { Host host=new Host(); DtProxy dtProxy=new DtProxy(); dtProxy.setRent(host); Rent proxy=(Rent)dtProxy.getProxy(); proxy.rent(); } }
使用AOP织入要导入依赖包
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.6</version> </dependency>
public class UserServiceImpl implements UserService{ public void add() { System.out.println("增加用户"); } public void delete() { System.out.println("删除用户"); } public void update() { System.out.println("更新用户"); } public void search() { System.out.println("查询用户"); } }
写增强类实现Spring的API
public class Log implements MethodBeforeAdvice { public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println(o.getClass().getName() + "的" + method.getName() + "方法被执行了"); } }
public class AfterLog implements AfterReturningAdvice { public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable { System.out.println("执行了" + o1.getClass().getName() +"的"+method.getName()+"方法," +"返回值:"+o); } }
最后在spring的配置文件中注册并实现aop切入
<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 id="userService" class="com.deng.Service.UserServiceImpl"></bean> <bean id="log" class="com.deng.Entity.Log"></bean> <bean id="afterLog" class="com.deng.Entity.AfterLog"></bean> <aop:config> <!--切入点 expression:表达式匹配要执行的方法--> <aop:pointcut id="pointcut" expression="execution(* com.deng.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>
自定义切入类
public class DiyPointCut { public void before(){ System.out.println("---------方法执行前---------"); } public void after(){ System.out.println("---------方法执行后---------"); } }
在Spring中配置
<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 id="userService" class="com.deng.Service.UserServiceImpl"></bean> <bean id="log" class="com.deng.Entity.Log"></bean> <bean id="afterLog" class="com.deng.Entity.AfterLog"></bean> <bean id="diy" class="com.deng.Entity.DiyPointCut"></bean> <aop:config> <aop:aspect ref="diy"> <aop:pointcut id="pointcut" expression="execution(* com.deng.Service.UserServiceImpl.*(..))"></aop:pointcut> <aop:before pointcut-ref="pointcut" method="before"></aop:before> <aop:after pointcut-ref="pointcut" method="after"></aop:after> </aop:aspect> </aop:config> </beans>
@Aspect public class DiyPointCut { @Before("execution(* com.deng.Service.UserServiceImpl.*(..))") public void before(){ System.out.println("---------方法执行前---------"); } @After("execution(* com.deng.Service.UserServiceImpl.*(..))") public void after(){ System.out.println("---------方法执行后---------"); } }
xml配置
<bean id="userService" class="com.deng.Service.UserServiceImpl"></bean> <bean id="diy" class="com.deng.Entity.DiyPointCut"></bean> <aop:aspectj-autoproxy/>
mybatis-spring
导入依赖
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
</dependencies>
在Mybatis中是通过SqlSessionFactoryBuilder来创建SqlSessionFactory的,而在MyBatis-Spring中是使用SqlSessionFactoryBean来创建的;
然后使用SqlSessionFactory来获取SqlSession,用他来执行映射语句。SqlSessionFactory有一个唯一的必要属性:用于JDBC的数据源DataSource。
SqlSessionTemplate是Myabtis-Spring的核心,是SqlSession的一个实现
可以使用SqlSessionFactory作为构造方法的参数来创建SqlSessionTemplate对象
beans.xml配置文件
sqlSessionFactory的属性configLocation和mapperLocation指定了mybatis和mapper的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 id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/mybatis? useSSL=true&useUnicode=true&characterEncoding=utf8&serverTimezone=UTC"></property> <property name="username" value="root"></property> <property name="password" value="13476110270dwx"></property> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <!--关联Mybatis--> <property name="configLocation" value="classpath:mybatis-config.xml"></property> <property name="mapperLocations" value="classpath:com/deng/dao/*.xml"></property> </bean> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg> </bean> <bean id="userDao" class="com.deng.dao.UserMapperImpl"> <property name="sqlSession" ref="sqlSession"></property> </bean> </beans>
增加接口实现类
public class UserMapperImpl implements UserMapper{ private SqlSessionTemplate sqlSession; public SqlSessionTemplate getSqlSession() { return sqlSession; } public void setSqlSession(SqlSessionTemplate sqlSession) { this.sqlSession = sqlSession; } public User getUser(int id) { UserMapper userMapper=sqlSession.getMapper(UserMapper.class); return userMapper.getUser(id); } }
测试
public void test1(){ ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml"); UserMapper userMapper=(UserMapper)context.getBean("userDao"); User user=userMapper.getUser(1); System.out.println(user); }
mybatis-config.xml中的配置文件并没有配置环境信息,SqlSessionFactoryBean会创建只有的mybatis环境
修改实现类
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{ public User getUser(int id){ UserMapper userMapper=(UserMapper)getSqlSession().getMapper(UserMapper.class); return userMapper.getUser(id); } }
修改bean配置
<bean id="userDao2" class="com.deng.dao.UserMapperImpl2"> <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> </bean>
测试
public void test1(){ ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml"); UserMapper userMapper=(UserMapper)context.getBean("userDao2"); User user=userMapper.getUser(1); System.out.println(user); }
编程式事务:将事务管理代码嵌入到业务方法中
声明式事务:将事务管理代码与业务方法分离,以声明的方式管理事务。通过Spring AOP框架支持声明式事务管理
在spring配置文件中,导入头文件tx
xmlns:tx="http://www.springframework.org/schema/tx" http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"
配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean>
配置事务通知
<!--配置事务通知--> <tx:advice id="txAdivce" transaction-manager="transactionManager"> <tx:attributes> <!--配置哪些方法需要使用什么的事务,配置事务的传播特性--> <tx:method name="gerUser" propagation="REQUIRED"/> </tx:attributes> </tx:advice>
事务的传播特性就是多个事务方法相互调用时,事务是如何在这些方法间传播的,Spring支持7种事务传播行为
spring默认的事务传播行为是propagation_required
织入事务
<!--配置aop织入事务--> <aop:config> <aop:pointcut id="txPointcut" expression="execution(* com.deng.dao.*.* (..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/> </aop:config>
原文:https://www.cnblogs.com/python-road/p/14716807.html