public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void save(){
bookDao.save();
}
}public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ... ");
}
} <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>2. 定义Spring管理的类(接口)
public interface BookService {
public void save();
}public class BookServiceImpl implements BookService {
private BookDao bookDao = new BookDaoImpl();
public void save() {
bookDao.save();
}
}3. 创建Spring配置文件,配置对应类作为 Spring 管理的 bean
<?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">
<!--2.配置bean-->
<!--bean标签标示配置bean
id属性标示给bean起名字
class属性表示给bean定义类型-->
<bean id="bookDao" class="top.bigdata.dao.impl.BookDaoImpl"/>
</beans>bean定义时id属性在同一个上下文中不能重复
4. 初始化 IOC 容器( Spring 核心容器 / Spring 容器),通过容器获取 bean
public class App {
public static void main(String[] args) {
//加载配置文件得到上下文对象,也就是容器对象
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//4.获取bean
BookService bookService = (BookService) ctx.getBean("bookService");
bookService.save();
}
}public class BookServiceImpl implements BookService {
//删除业务层中使用new的方式创建的dao对象
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
//提供对应的set方法
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}<?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="bookDao" class="top.bigdata.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="top.bigdata.service.impl.BookServiceImpl">
<!--配置server与dao的关系-->
<!--
property标签表示配置当前bean的属性
name属性表示配置哪一个具体的属性
ref属性表示参照哪一个bean
-->
<property name="bookDao" ref="bookDao"/>
</bean>
</beans><bean id="" class=""/> <bean id="bookDao" class="top.bigdata.dao.impl.BookDaoImpl"/><!--name:为bean指定别名,别名可以有多个,使用逗号,分号,空格进行分隔-->
<bean id="bookService" name="service service4 bookEbi" class="top.bigdata.service.impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"/><!--这里ref的属性值可以是下面name的属性值dao,建议使用下面id进行注入-->
</bean>
<!--scope:为bean设置作用范围,可选值为单例singloton,非单例prototype-->
<bean id="bookDao" name="dao" class="top.bigdata.dao.impl.BookDaoImpl"/>public class AppForName {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//此处根据bean标签的id属性和name属性的任意一个值来获取bean对象
BookService bookService = (BookService) ctx.getBean("service4");
bookService.save();
}
}<bean id="bookDao" name="dao" class="top.bigdata.dao.impl.BookDaoImpl" scope="prototype"/>构造方法
public class BookDaoImpl implements BookDao {
public BookDaoImpl() {
//spring创建bean的时候调用的是无参构造
System.out.println("book dao constructor is running ....");
}
public void save() {
System.out.println("book dao save ...");
}
}<bean id="bookDao" class="top.bigdata.dao.impl.BookDaoImpl"/>public class AppForInstanceBook {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
}
}静态工厂
public interface OrderDao {
public void save();
}
public class OrderDaoFactory { //提供一个静态方法
public static OrderDao getOrderDao(){
System.out.println("factory setup....");
return new OrderDaoImpl();
}
}配置:
<bean id="orderDao" class="top.bigdata.factory.OrderDaoFactory" factory-method="getOrderDao"/>实例工厂
<bean id="userFactory" class="top.bigdata.factory.UserDaoFactory"/> <!--先配置工厂的bean-->
<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>public class UserDaoFactory {
public UserDao getUserDao(){
return new UserDaoImpl();
}
}使用 FactoryBean 实例化 bean
//FactoryBean创建对象
public class UserDaoFactoryBean implements FactoryBean<UserDao> { //代替上面 UserDaoFactory 中创建对象的方法
//代替原始实例工厂UserDaoFactory中创建对象的方法
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
public Class<?> getObjectType() {
return UserDao.class;
}
/*一般情况下都会采用单例,不需要重写 isSingleton 方法*/
public boolean isSingleton() {
return true; //此时是单例的bean对象,false为非单例对象
}
}<bean id="userDao" class="top.bigdata.factory.UserDaoFactoryBean"/><bean id="bookDao" class="top.bigdata.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>.
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
//表示bean初始化对应的操作
public void init(){
System.out.println("init...");
}
//表示bean销毁前对应的操作
public void destory(){
System.out.println("destory...");
}
}public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
public void destroy() throws Exception {
System.out.println("service destroy");
}
public void afterPropertiesSet() throws Exception { //属性设置之后
System.out.println("service init");
}
}bean 销毁时机
ctx.close();ctx.registerShutdownHook();public class AppForLifeCycle {
public static void main( String[] args ) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
/*注册关闭钩子函数,在虚拟机退出之前回调此函数,先关闭容器*/
ctx.registerShutdownHook();
/*关闭容器*/
ctx.close();//暴力
}
}public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
} <!--注入引用类型-->
<bean id="bookService" class="top.bigdata.service.impl.BookServiceImpl">
<!--property标签:设置注入属性-->
<!--name属性:设置注入的属性名,实际是set方法对应的名称(BookServiceImpl)中对象声明-->
<!--ref属性:设置注入引用类型bean的id或name-->
<property name="bookDao" ref="bookDao"/>
<property name="userDao" ref="userDao"/>
</bean>public class BookDaoImpl implements BookDao {
private String databaseName;
private int connectionNum;
//setter注入需要提供要注入对象的set方法
public void setConnectionNum(int connectionNum) {
this.connectionNum = connectionNum;
}
//setter注入需要提供要注入对象的set方法
public void setDatabaseName(String databaseName) {
this.databaseName = databaseName;
}
public void save() {
System.out.println("book dao save ..."+databaseName+","+connectionNum);
}
} <!--注入简单类型-->
<bean id="bookDao" class="top.bigdata.dao.impl.BookDaoImpl">
<!--property标签:设置注入属性-->
<!--name属性:设置注入的属性名,实际是set方法对应的名称-->
<!--value属性:设置注入简单类型数据值-->
<property name="connectionNum" value="100"/>
<property name="databaseName" value="mysql"/>
</bean>
<bean id="userDao" class="top.bigdata.dao.impl.UserDaoImpl"/><property name="connectionNum" value="abc"/>
public class BookServiceImpl implements BookService{
private BookDao bookDao;
private UserDao userDao;
public BookServiceImpl(BookDao bookDao, UserDao userDao) {
this.bookDao = bookDao;
this.userDao = userDao;
}
public void save() {
System.out.println("book service save ...");
bookDao.save();
userDao.save();
}
}<bean id="userDao" class="top.bigdata.dao.impl.UserDaoImpl"/>
<bean id="bookService" class="top.bigdata.service.impl.BookServiceImpl">
<constructor-arg name="userDao" ref="userDao"/>
<constructor-arg name="bookDao" ref="bookDao"/> <!--此处的name是形参的名-->
</bean>public class BookDaoImpl implements BookDao {
private String databaseName;
private int connectionNum;
public BookDaoImpl(String databaseName, int connectionNum) {
this.databaseName = databaseName;
this.connectionNum = connectionNum;
}
public void save() {
System.out.println("book dao save ..." + databaseName + "," + connectionNum);
}
}<bean id="bookDao" class="top.bigdata.dao.impl.BookDaoImpl">
<!--根据构造方法参数名称注入-->
<constructor-arg name="connectionNum" value="10"/>
<constructor-arg name="databaseName" value="mysql"/>
</bean> <!--解决形参名称的问题,与形参名不耦合-->
<bean id="bookDao" class="top.bigdata.dao.impl.BookDaoImpl">
<!--根据构造方法参数类型注入-->
<constructor-arg type="int" value="10"/>
<constructor-arg type="java.lang.String" value="mysql"/>
</bean>
<bean id="userDao" class="top.bigdata.dao.impl.UserDaoImpl"/>
<bean id="bookService" class="top.bigdata.service.impl.BookServiceImpl">
<constructor-arg name="userDao" ref="userDao"/>
<constructor-arg name="bookDao" ref="bookDao"/>
</bean> <!--解决参数类型重复问题,使用位置解决参数匹配-->
<bean id="bookDao" class="top.bigdata.dao.impl.BookDaoImpl">
<!--根据构造方法参数位置注入-->
<constructor-arg index="0" value="mysql"/>
<constructor-arg index="1" value="100"/>
</bean>
<bean id="userDao" class="top.bigdata.dao.impl.UserDaoImpl"/>
<bean id="bookService" class="top.bigdata.service.impl.BookServiceImpl">
<constructor-arg name="userDao" ref="userDao"/>
<constructor-arg name="bookDao" ref="bookDao"/>
</bean> <bean class="top.bigdata.dao.impl.BookDaoImpl"/>
<!--autowire属性:开启自动装配,通常使用按类型装配-->
<bean id="bookService" class="top.bigdata.service.impl.BookServiceImpl" autowire="byType"/>public class BookServiceImpl implements BookService{
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}public interface BookDao {
public void save();
}
public class BookDaoImpl implements BookDao {
private int[] array;
private List<String> list;
private Set<String> set;
private Map<String, String> map;
private Properties properties;
public void setArray(int[] array) {
this.array = array;
}
public void setList(List<String> list) {
this.list = list;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public void save() {
System.out.println("book dao save ...");
System.out.println("遍历数组:" + Arrays.toString(array));
System.out.println("遍历List" + list);
System.out.println("遍历Set" + set);
System.out.println("遍历Map" + map);
System.out.println("遍历Properties" + properties);
}
}<?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="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
</bean>
</beans>public class AppForDICollection {
public static void main( String[] args ) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
}
} <!--数组注入-->
<property name="array">
<array>
<value>100</value>
<value>200</value>
<value>300</value>
</array>
</property> <!--list集合注入-->
<property name="list">
<list>
<value>itcast</value>
<value>itheima</value>
<value>boxuegu</value>
<value>chuanzhihui</value>
</list>
</property> <!--set集合注入-->
<property name="set">
<set>
<value>itcast</value>
<value>itheima</value>
<value>boxuegu</value>
<value>boxuegu</value>
</set>
</property> <!--map集合注入-->
<property name="map">
<map>
<entry key="country" value="china"/>
<entry key="province" value="henan"/>
<entry key="city" value="kaifeng"/>
</map>
</property> <!--Properties注入-->
<property name="properties">
<props>
<prop key="country">china</prop>
<prop key="province">henan</prop>
<prop key="city">kaifeng</prop>
</props>
</property>说明:
<array>、<list>、<set>、<map>、<props>标签<list>和<array>标签是可以混用<value>标签改成<ref>标签,这种方式用的比较少 <dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency><!-- 管理DruidDataSource对象-->
<bean class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/> <!--driverClassName:数据库驱动-->
<property name="url" value="jdbc:mysql://localhost:3306/spring_db"/> <!--url:数据库连接地址-->
<property name="username" value="root"/> <!--username:数据库连接用户名-->
<property name="password" value="123456"/> <!--password:数据库连接密码-->
</bean><dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="user" value="root"/>
<property name="password" value="123456"/>
<property name="maxPoolSize" value="1000"/> <!--最大连接池的数量-->
</bean><dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>Druid 和 C3P0 在没导入 mysql 驱动前提下一个没报错一个报错,说明 Druid 在初始化的时候没有去加载驱动,而 C3P0 刚好相反
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
jdbc.username=root
jdbc.password=123456<?xml version="1.0" encoding="UTF-8"?>
<!--xmlns:context开启一个新的命名空间,把上面的bean都换成context-->
<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><context:property-placeholder location="jdbc.properties"/><property name="username" value="${jdbc.username}"/><?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:property-placeholder location="jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
</beans><context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/><context:property-placeholder location="jdbc.properties,jdbc2.properties"/><context:property-placeholder location="*.properties"/><context:property-placeholder location="classpath:*.properties"/><context:property-placeholder location="classpath*:*.properties"/>ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\applicationContext.xml");ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml","bean2.xml");BookDao bookDao = (BookDao) ctx.getBean("bookDao");BookDao bookDao = ctx.getBean("bookDao", BookDao.class);BookDao bookDao = ctx.getBean(BookDao.class);public class AppForBeanFactory {
public static void main(String[] args) {
Resource resources = new ClassPathResource("applicationContext.xml");
BeanFactory bf = new XmlBeanFactory(resources);
BookDao bookDao = bf.getBean(BookDao.class);
bookDao.save();
}
}<bean
id="bookDao" bean的Id
name="dao bookDaoImpl daoImpl" bean的别名
class="top.bigdata.dao.impl.BookDaoImpl" bean类型,静态工厂类,FactoryBean类
scope="singleton" 控制bean的实例数量
init-method="init" 生命周期初始化方法
destroy-method="destory" 生命周期销毁方法
autowire="byType" 自动装配类型
factory-method="getInstance" bean工厂方法,应用于静态工厂或实例工厂
factory-bean="top.bigdata.factory .BookDaoFactory" 实例工厂bean
lazy-init="true" 控制bean延迟加载
/>@Component
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}<context:component-scan base-package="top.bigdata"/>@Repository("bookDao")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
@Service
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}public class App {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
System.out.println(bookDao);
//按类型获取bean
BookService bookService = ctx.getBean(BookService.class);
System.out.println(bookService);
}
}Spring3.0 升级了纯注解开发模式,使用 Java 类替代配置文件,开启了 Spring 快速开发赛道
//声明当前类为Spring配置类,用这个类代替配置文件
@Configuration
//设置bean扫描路径,多个路径书写为字符串数组格式
@ComponentScan({"top.bigdata.service","top.bigdata.dao"})
public class SpringConfig {
}public class AppForAnnotation {
public static void main(String[] args) {
//AnnotationConfigApplicationContext加载Spring配置类初始化Spring容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
System.out.println(bookDao);
//按类型获取bean
BookService bookService = ctx.getBean(BookService.class);
System.out.println(bookService);
}
}@ComponentScan({"top.bigdata.service","top.bigdata.dao"})ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//转换为
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);@Repository
//@Scope设置bean的作用范围
@Scope("singleton")//单例;换成prototype,非单例
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
//@PostConstruct设置bean的初始化方法
@PostConstruct
public void init() {
System.out.println("init ...");
}
//@PreDestroy设置bean的销毁方法
@PreDestroy
public void destroy() {
System.out.println("destroy ...");
}
}@Service
public class BookServiceImpl implements BookService {
//@Autowired:注入引用类型,自动装配模式,默认按类型装配
@Autowired
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}@Service
public class BookServiceImpl implements BookService {
//@Qualifier:自动装配bean时按bean名称装配,如果有相同类型的bean写
@Qualifier("bookDao")
private BookDao bookDao;
}
}使用 @Value 实现简单类型注入
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
//@Value:注入简单类型(无需提供set方法)
@Value("${name}")
private String name;
}使用 @PropertySource 注解加载 properties 文件
@Configuration
@ComponentScan("com.itheima")
//@PropertySource加载properties配置文件
@PropertySource({"jdbc.properties"})
public class SpringConfig {
}使用独立的配置类管理第三方 bean
@Configuration
public class JdbcConfig {
//1.定义一个方法获得要管理的对象
//2.添加@Bean,表示当前方法的返回值是一个bean
//@Bean修饰的方法,形参根据类型自动装配
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("123456");
return ds;
}
}@Configuration
//@Import:导入配置信息
@Import({JdbcConfig.class})
public class SpringConfig {
}@Configuration
@ComponentScan({"top.bigdata.config", "top.bigdata.service"})
public class SpringConfig {
}public class JdbcConfig {
@Value("com.mysql.jdbc.Driver")
private String driver;
@Value("jdbc:mysql://localhost:3306/spring_db")
private String url;
@Value("root")
private String userName;
@Value("123456")
private String password;
@Bean
public DataSource dataSource(BookDao bookDao){
System.out.println(bookDao);
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}
} @Bean
public DataSource dataSource(BookDao bookDao){
System.out.println(bookDao);
DruidDataSource ds = new DruidDataSource();
//属性设置
return ds;
}<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>public class App {
public static void main(String[] args) throws IOException {
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 2. 加载SqlMapConfig.xml配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml.bak");
// 3. 创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
// 4. 获取SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 5. 执行SqlSession对象执行查询,获取结果User
AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
Account ac = accountDao.findById(2);
System.out.println(ac);
// 6. 释放资源
sqlSession.close();
}
}<configuration>
<properties resource="jdbc.properties"></properties>
<!-- -->
<typeAliases>
<package name="top.bigdata.domain"/>
</typeAliases>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!-- -->
<mappers>
<package name="top.bigdata.dao"></package>
</mappers>
</configuration>//定义bean,SqlSessionFactoryBean,用于产生SqlSessionFactory对象
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
ssfb.setTypeAliasesPackage("top.bigdata.domain");
ssfb.setDataSource(dataSource);
return ssfb;
}//定义bean,返回MapperScannerConfigurer对象
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer msc = new MapperScannerConfigurer();
msc.setBasePackage("top.bigdata.dao");
return msc;
}//设置类运行器
@RunWith(SpringJUnit4ClassRunner.class)
//设置Spring环境对应的配置类
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {
//支持自动装配注入bean
@Autowired
private AccountService accountService;
@Test
public void testFindById(){
System.out.println(accountService.findById(1)); //加载id为1的
}
@Test
public void testFindAll(){
System.out.println(accountService.findAll()); //加载全部
}
} <dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>public interface BookDao {
public void save();
public void update();
}@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println(System.currentTimeMillis());
System.out.println("book dao save ...");
}
public void update(){
System.out.println("book dao update ...");
}
}public class MyAdvice {
public void method(){
System.out.println(System.currentTimeMillis());
}
}public class MyAdvice {
//设置切入点,要求配置在方法上方
@Pointcut("execution(void top.bigdata.dao.BookDao.update())")
private void pt(){}
}//通知类必须配置成Spring管理的bean
@Component
//设置当前类为切面类类
@Aspect
public class MyAdvice {
//设置切入点,要求配置在方法上方
@Pointcut("execution(void top.bigdata.dao.BookDao.update())")
private void pt(){}
//设置在切入点pt()的前面运行当前操作(前置通知)
@Before("pt()")
public void method(){
System.out.println(System.currentTimeMillis());
}
}@Configuration
@ComponentScan("top.bigdata")
//开启注解开发AOP功能
@EnableAspectJAutoProxy
public class SpringConfig {
}execution(void top.bigdata.dao.BookDao.update())execution(public User top.bigdata.service.UserService.findById(int))*:单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现
execution(public * top.bigdata.*.UserService.find* (*)).. :多个连续的任意符号,可以独立出现,常用于简化报名与参数的书写
execution(public User com..UserService.findById(..))+:专用于匹配子类类型
execution(* *..*Service+.*(..))execution(void top.bigdata.dao.BookDao.update())
匹配接口,能匹配到
execution(void top.bigdata.dao.impl.BookDaoImpl.update())
匹配实现类,能匹配到
execution(* top.bigdata.dao.impl.BookDaoImpl.update())
返回值任意,能匹配到
execution(* top.bigdata.dao.impl.BookDaoImpl.update(*))
返回值任意,但是update方法必须要有一个参数,无法匹配,要想匹配需要在update接口和实现类添加参数
execution(void com.*.*.*.*.update())
返回值为void,com包下的任意包三层包下的任意类的update方法,匹配到的是实现类,能匹配
execution(void com.*.*.*.update())
返回值为void,com包下的任意两层包下的任意类的update方法,匹配到的是接口,能匹配
execution(void *..update())
返回值为void,方法名是update的任意包下的任意类,能匹配
execution(* *..*(..))
匹配项目中任意类的任意方法,能匹配,但是不建议使用这种方式,影响范围广
execution(* *..u*(..))
匹配项目中任意包任意类下只要以u开头的方法,update方法能满足,能匹配
execution(* *..*e(..))
匹配项目中任意包任意类下只要以e结尾的方法,update和save方法能满足,能匹配
execution(void com..*())
返回值为void,com包下的任意包任意类任意方法,能匹配,*代表的是方法
execution(* top.bigdata.*.*Service.find*(..))
将项目中所有业务层方法的以find开头的方法匹配
execution(* top.bigdata.*.*Service.save*(..))
将项目中所有业务层方法的以save开头的方法匹配 @Pointcut("execution(void top.bigdata.dao.BookDao.update())")
private void pt(){} @Around("pt()")
public Object aroundSelect(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around before advice ...");
//通过参数ProceedingJoinPoint对原始方法进行调用获取一个返回值
Integer ret = (Integer) pjp.proceed();
System.out.println("around after advice ...");
return ret;
}名称 | @After |
|---|---|
类型 | 方法注解 |
位置 | 通知方法定义上方 |
作用 | 设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法后运行 |
名称 | @AfterReturning |
|---|---|
类型 | 方法注解 |
位置 | 通知方法定义上方 |
作用 | 设置当前通知方法与切入点之间绑定关系,当前通知方法在原始切入点方法正常执行完毕后执行 |
名称 | @AfterThrowing |
|---|---|
类型 | 方法注解 |
位置 | 通知方法定义上方 |
作用 | 设置当前通知方法与切入点之间绑定关系,当前通知方法在原始切入点方法运行抛出异常后执行 |
名称 | @Around |
|---|---|
类型 | 方法注解 |
位置 | 通知方法定义上方 |
作用 | 设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前后运行 |
//设置环绕通知,在原始操作的运行前后记录执行时间
@Around("ProjectAdvice.servicePt()")
public void runSpeed(ProceedingJoinPoint pjp) throws Throwable {
//获取执行的签名对象信息
Signature signature = pjp.getSignature();
String className = signature.getDeclaringTypeName();
String methodName = signature.getName();
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
pjp.proceed();
}
long end = System.currentTimeMillis();
System.out.println("万次执行:"+ className+"."+methodName+"---->" +(end-start) + "ms");
}@Before("pt()")
public void before(JoinPoint jp) {
Object[] args = jp.getArgs();
System.out.println(Arrays.toString(args));
System.out.println("before advice ..." );
} @Around("pt()")
public Object around(ProceedingJoinPoint pjp) {
Object[] args = pjp.getArgs();
System.out.println(Arrays.toString(args));
Object ret = pjp.proceed();
return ret;
}//设置返回后通知获取原始方法的返回值,要求returning属性值必须与方法形参名相同
@AfterReturning(value = "pt()",returning = "ret")
public void afterReturning(JoinPoint jp,String ret) {
System.out.println("afterReturning advice ..."+ret);
} @Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable{
Object ret = pjp.proceed();
return ret;
}抛异常:
//设置抛出异常后通知获取原始方法运行时抛出的异常对象,要求throwing属性值必须与方法形参名相同
@AfterThrowing(value = "pt()",throwing = "t")
public void afterThrowing(Throwable t) {
System.out.println("afterThrowing advice ..."+t);
} @Around("pt()")
public Object around(ProceedingJoinPoint pjp) {
Object ret = null;
try {
ret = pjp.proceed(args);
} catch (Throwable t) {
t.printStackTrace();
}
return ret;
}百度网盘密码数据兼容处理
@Around("DataAdvice.servicePt()")
public Object trimStr(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
for (int i = 0; i < args.length; i++) {
//判断参数是不是字符串
if(args[i].getClass().equals(String.class)){
args[i] = args[i].toString().trim();
}
}
Object ret = pjp.proceed(args);
return ret;
}AOP的核心概念
切入点表达式
execution(* top.bigdata.service.*Service.*(..))*:匹配任意符号(常用).. :匹配多个连续的任意符号(常用)+:匹配子类类型五种通知类型
通知中获取参数
银行账户转账
public interface AccountService {
/**
* 转账操作
* @param out 传出方
* @param in 转入方
* @param money 金额
*/
//配置当前接口方法具有事务
@Transactional //开启Spring事务
public void transfer(String out,String in ,Double money) ;
}//配置事务管理器,mybatis使用的是jdbc事务
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
//开启注解式事务驱动
@EnableTransactionManagement
public class SpringConfig {
} @Transactional //开启Spring事务
public void transfer(String out,String in ,Double money) { //将 Spring 开启的事务叫事务管理员
accountDao.outMoney(out,money);
accountDao.inMoney(in,money);
} @Update("update tbl_account set money = money + #{money} where name = #{name}")
void inMoney(@Param("name") String name, @Param("money") Double money);
//加入到Spring事务中的成员叫 事务协调员
@Update("update tbl_account set money = money - #{money} where name = #{name}")
void outMoney(@Param("name") String name, @Param("money") Double money);相关配置
属性 | 作用 | 实例 |
|---|---|---|
readOnly | 设置是否为只读事务 | readOnly=true 只读事务 |
timeout | 设置事务超时时间 | timeout = -1 (永不超时) |
rollbackFor | 设置事务回滚异常(class) | rollbackFor={NullPointException.class} |
rollbackForClassName | 设置事务回滚异常(String) | 同上格式为字符串 |
noRollbackFor | 设置事务不回滚异常(class) | noRollbackFor={NullPointException.class} |
noRollbackForClassName | 设置事务不回滚异常(String) | 同上格式为字符串 |
propagation | 设置事务传播行为 | …… |
@Service
public class LogServiceImpl implements LogService {
@Autowired
private LogDao logDao;
//propagation设置事务属性:传播行为设置为当前操作需要开启新事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(String out,String in,Double money ) {
logDao.log("转账操作由"+out+"到"+in+",金额:"+money);
}
}Spring基础好像也就这么多了,欢迎大家留言指正呦~~
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。