Spring基础-02
Spring基础-02
1.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"
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/>
<!-- 配置要扫描的包 -->
<context:component-scan base-package="com.my.domain"/>
</beans>
- 注解配置。
- @Component将bean注入到容器。同作用的注解还有@Controller、@Service、@Repository。
- @Scope配置bean的作用域。
- @Value可以作用在属性和方法中,为属性注入值。
- @Autowired、@Qualifier、@Resource,自动装配。
@Component
@Scope(scopeName = "singleton")
public class Person {
@Value("bob")
private String name;
@Value("tom") //可以作用在方法上
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
2.Java代码配置Spring容器
- 配置Spring容器。
- @Configuration,声明为一个配置类。
- @Component,将bean注入容器。
- @Import,导入更多的配置类。
- @Bean,将返回的bean注入容器。
- @ComponentScan,配置要扫描的包。
- @Order,多个配置文件时,定义加载配置文件的顺序。
@Configuration
@Component
@Import(AspectConfig.class) //@Import 对于多个配置类,可以使用@Import来引入
public class SpringConfig {
//@Bean 默认使用方法名作为bean的id。可以使用name、value修改bean的id。
@Bean(name = "person")
public Person getPerson() {
return new Person();
}
}
public class AspectConfig {
}
- 启动Spring容器,使用AnnotationConfigApplicationContext。
public class UserTest {
@Test
public void test01() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
Person person = context.getBean("person", Person.class);
System.out.println(person.getName());
}
}
3.静态代理
- 被代理对象。
public interface ISport {
void sport();
}
public class SportImpl implements ISport {
@Override
public void sport() {
System.out.println("sport");
}
}
- 代理对象。
public class ProxySport implements ISport{
private ISport sport;
public ProxySport(ISport sport) {
this.sport = sport;
}
@Override
public void sport() {
System.out.println("=====start=====");
sport.sport();
System.out.println("=====end=====");
}
}
- 客户端。
public class Client {
public static void main(String[] args) {
SportImpl sport = new SportImpl();
ProxySport proxySport = new ProxySport(sport);
proxySport.sport();
}
}
- 缺点。增加功能时需要修改原有代码;并且增加一个功能,代码量翻倍,原有类和代理类有需要实现这个方法。
4.动态代理
- 被代理对象。
public interface ISport {
void sport();
}
public class SportImpl implements ISport {
@Override
public void sport() {
System.out.println("sport");
}
}
- 代理对象
public class SportProxy implements InvocationHandler {
private ISport sport;
public SportProxy(ISport sport) {
this.sport = sport;
}
public ISport getInstance() {
ISport sportProxy = (ISport) Proxy.newProxyInstance(this.getClass().getClassLoader(),
sport.getClass().getInterfaces(), this);
return sportProxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("日志记录");
method.invoke(sport, args);
return proxy;
}
}
- 客户端
public class Client {
public static void main(String[] args) {
SportImpl sport = new SportImpl();
SportProxy proxy = new SportProxy(sport);
ISport proxySport = proxy.getInstance();
proxySport.sport();
}
}
- 优点。Java自动生成代理对象;对于像日志打印等功能,被代理对象功能增加了,但是代理对象SportProxy的invoke方法依然不变,只需要记录日志即可。
- 动态代理的实现方式。JDK动态代理,基于接口;cglib,基于类的动态代理。
5.Spring AOP
- 需要引入的依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
-
Spring AOP,使用Spring API实现。
- 实体业务类。
public interface IUserService { void add(); } public class UserService implements IUserService{ @Override public void add() { System.out.println("add====="); } }
- 通知类。
public class AfterLog implements AfterReturningAdvice { @Override public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable { System.out.println("执行完成"); } } public class BeforeLog implements MethodBeforeAdvice { @Override public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println("开始运行"); } }
- 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" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userService" class="com.my.UserService" /> <bean id="beforeLog" class="com.my.BeforeLog" /> <bean id="afterLog" class="com.my.AfterLog" /> <aop:config> <!-- 切入点 --> <aop:pointcut id="pointcut" expression="execution(* com.my.*.*(..))"/> <!-- 通知 --> <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut" /> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut" /> </aop:config> </beans>
-
Spring AOP,配置文件实现。
- 切面类。
public class Log { public void before() { System.out.println("=====before====="); } public void after() { System.out.println("=====after====="); } }
- 配置文件。
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userService" class="com.my.UserService" /> <bean id="log" class="com.my.Log"/> <aop:config> <!-- 切面 --> <aop:aspect id="aspect" ref="log"> <!-- 切入点 --> <aop:pointcut id="pointcut" expression="execution(* com.my.*.*(..))"/> <!-- 通知 --> <aop:before method="before" pointcut-ref="pointcut" /> <aop:after method="after" pointcut-ref="pointcut" /> </aop:aspect> </aop:config> </beans>
-
Spring AOP,注解实现。
- 切面。
@Aspect public class LogAspect { @Pointcut("execution(* com.my.*.*(..))") public void log(){} @Before("log()") public void before() { System.out.println("before do"); } @Around("log()") public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("do 1"); pjp.proceed(); System.out.println(pjp.getSignature().getClass().getName() + "." + pjp.getSignature().getName()); System.out.println("do 2"); return null; } }
- xml配置,开启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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userService" class="com.my.UserService" /> <!-- 将切面注入。 --> <bean id="log" class="com.my.LogAspect"/> <!-- AOP使用注解实现时,需要开启自动代理的配置。--> <aop:aspectj-autoproxy/> </beans>
-
Spring AOP,xml中配置不同的实现方式。
- proxy-target-class="false",Spring默认配置,使用JDK动态代理。
- proxy-target-class="true",使用cglib代理。
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="userService" class="com.my.UserService" />
<bean id="log" class="com.my.LogAspect"/>
<!--proxy-target-class="false" 默认,使用的是JDK动态代理。
proxy-target-class="true" 使用cglib代理。-->
<aop:aspectj-autoproxy proxy-target-class="false"/>
</beans>
6.Spring整合Mybatis,通过注入SqlSessionTemplate实现
- 需要导入的依赖。
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.8</version>
</dependency>
<!-- AOP-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- 整合包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
</dependencies>
- mybatis配置文件。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.my.dao.User"/>
</typeAliases>
</configuration>
- Java类
@Data
public class User {
private Integer id;
private String name;
private Integer age;
}
- mapper.xml文件。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.my.dao.UserDao">
<select id="getAll" resultType="com.my.dao.User">
select * from tb_user
</select>
</mapper>
- 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://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 name="url" value="jdbc:mysql://localhost:3306/springboot"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- mybatis配置文件的位置 -->
<property name="configLocation" value="mybatis-config.xml"/>
<!-- mapper的位置 -->
<property name="mapperLocations" value="classpath*:com/my/dao/*.xml"/>
</bean>
<bean id="template" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory"/>
</bean>
<bean id="userDao" class="com.my.dao.impl.UserDaoImpl">
<property name="template" ref="template"/>
</bean>
</beans>
- 测试类,通过注入SqlSessionTemplate来获取mapper对象。
public interface UserDao {
List<User> getAll();
}
public class UserDaoImpl implements UserDao {
private SqlSessionTemplate template;
public void setTemplate(SqlSessionTemplate template) {
this.template = template;
}
@Override
public List<User> getAll() {
UserDao userDao = template.getMapper(UserDao.class);
return userDao.getAll();
}
}
public class UserTest {
@Test
public void test01() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserDao userDao = context.getBean("userDao", UserDao.class);
List<User> users = userDao.getAll();
users.forEach(System.out::print);
}
}
7.Spring整合Mybatis,通过继承SqlSessionDaoSupport实现
- 继承SqlSessionDaoSupport来获取SqlSession。
public class UserDaoImpl2 extends SqlSessionDaoSupport implements UserDao {
@Override
public List<User> getAll() {
UserDao userDao = getSqlSession().getMapper(UserDao.class);
return userDao.getAll();
}
}
- 继承SqlSessionDaoSupport的实现方式,需要注入sqlSessionFactory。
<?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
https://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 name="url" value="jdbc:mysql://localhost:3306/springboot"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- mybatis配置文件的位置 -->
<property name="configLocation" value="mybatis-config.xml"/>
<!-- mapper的位置 -->
<property name="mapperLocations" value="classpath*:com/my/dao/*.xml"/>
</bean>
<!-- 继承SqlSessionDaoSupport的实现方式,需要注入sqlSessionFactory。 -->
<bean id="userDao2" class="com.my.dao.impl.UserDaoImpl2">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
</beans>
8.Spring事务配置,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"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/springboot"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- mybatis配置文件的位置 -->
<property name="configLocation" value="mybatis-config.xml"/>
<!-- mapper的位置 -->
<property name="mapperLocations" value="classpath*:com/my/dao/*.xml"/>
</bean>
<bean id="template" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory"/>
</bean>
<bean id="userDao" class="com.my.dao.impl.UserDaoImpl">
<property name="template" ref="template"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<aop:config>
<!-- 切点 -->
<aop:pointcut id="pointcut" expression="execution(* com.my.dao.impl.*.*(..))"/>
<aop:advisor advice-ref="advice" pointcut-ref="pointcut"/>
</aop:config>
<tx:advice id="advice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="query" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
</beans>