- spring是开源对轻量级框架
- spring核心主要两部分
- aop
- 面向切面编程,扩展功能不是修改源代码实现
- aop采用横向抽取机制,取代了传统纵向继承体系重复代码(性能监视、事务管理、安全检查、缓存)
- 使用动态代理方式实现横向抽取机制
- 使用JDK动态代理,针对有接口情况
- 创建接口类的平级对象
- 这个对象不是真正对象,是代理对象,实现和类相同的功能
- 使用cglib动态代理,针对没有接口情况
- 创建类的子类的代理对象
- 在子类里面调用父类的方法完成增强
-
- aop操作术语
- Joinnoint(连接点)
- 所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
- 类里面那些方法可以被增强,这些方法称为连接点
- Pointcut(切入点)
- 所谓切入点是指我们要对那些Joinnoint进行拦截的定义
- 在类里面可以有很多的方法被增强,而实际增强的方法称为切入点
- Advice(通知/增强)
- 所谓通知是指拦截到Joinnoint之后所要做的事情就是通知
- 通知分类
- 前置通知:在方法之前执行
- 后置通知:在方法之后执行
- 异常通知:方法出现异常
- 最终通知:在后置之后执行
- 环绕通知:在方法之前和之后执行
- 功能扩展的逻辑,称为增强。
- Introduction(引介)
- 引介是一种特殊的通知在不修改类代码的前提下,Introduction可以在运行期为类动态地添加一些方法或Field
- Target(目标对象)
- 代理的目标对象(要增强的类)
- 增强方法所在的类,叫做目标对象
- Weaving(织入)
- 是把增强应用到目标的过程
- 把advice应用到target的过程
- Proxy(代理)
- 一个类被ACP织入增强后,就产生一个结果代理类
- Aspect(切面)
- 是切入点和通知(引介)的结合
- 把增强应用到具体方法上面,过程称为切面
- Joinnoint(连接点)
- aop操作术语
-
- AspectJ
- AspectJ是一个基于Java语言的AOP框架
- AspectJ是一个面向切面的框架,它扩展了Java语言
- AspectJ定义了aop语法,所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件
AspectJ实现aop
- 导入jar包spring-aop-4.3.5.RELEASE.jar、spring-aspects-4.3.5.RELEASE.jar、aspectjweaver-1.9.2.jar、aopalliance-1.0.jar
- 导入约束
<?xml version="1.0" encoding="UTF-8" ?> <!-- http://www.springframework.org/schema/context/spring-context.xsd:用于注解的约束 http://www.springframework.org/schema/aop/spring-aop.xsd:用于aop的约束 --> <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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> </beans>
- 具体实现
- 基于aspectJ的xml配置
/** * */ public class Test02 { public void test02() { System.out.println("前置增强"); } public void test02After(){ System.out.println("后置增强"); } /** * * @param proceedingJoinPoint 被增强的的方法 */ public void test02Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕增强前"); proceedingJoinPoint.proceed(); System.out.println("环绕增强后"); } } /** * */ public class Test01 { public void test01(){ 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: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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 配置对象 --> <bean id="test01" class="cn.muriel.auto.aop.Test01"/> <bean id="test02" class="cn.muriel.auto.aop.Test02"/> <!-- 配置aop操作 --> <aop:config> <!-- 配置切入点(*代表匹配所有) execution(<访问修饰符> ? <返回类型><方法名>(<参数>)<异常>) execution(* cn.muriel.auto.aop.Test01.test01(..)) execution(* cn.muriel.auto.aop.Test01.*(..)) execution(* *.*(..)) execution(* save*(..))//匹配所有save开头的方法 --> <aop:pointcut id="pointcut1" expression="execution(* cn.muriel.auto.aop.Test01.test01(..))"/> <!-- 配置增强类型 --> <aop:aspect ref="test02"> <!-- 配置增强类型 method:增强类里面使用哪个方法作为前置 --> <!-- 前置增强 --> <aop:before method="test02" pointcut-ref="pointcut1"/> <!-- 后置增强 --> <aop:after-returning method="test02After" pointcut-ref="pointcut1"/> <!-- 环绕增强 --> <aop:around method="test02Around" pointcut-ref="pointcut1"/> </aop:aspect> </aop:config> </beans> /** * 测试代码 */ public class TestUtil { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("aop/aop.xml"); Test01 test01 = (Test01) applicationContext.getBean("test01"); test01.test01(); } }
- 基于aspectJ的注解方式
@Aspect public class Test02 { @Before(value = "execution(* cn.muriel.auto.aop.Test01.test01(..))") public void test02() { System.out.println("前置增强"); } @AfterReturning(value = "execution(* cn.muriel.auto.aop.Test01.test01(..))") public void test02After(){ System.out.println("后置增强"); } /** * * @param proceedingJoinPoint 被增强的的方法 */ @Around(value = "execution(* cn.muriel.auto.aop.Test01.test01(..))") public void test02Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕增强前"); proceedingJoinPoint.proceed(); System.out.println("环绕增强后"); } } /** * */ public class Test01 { public void test01(){ 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: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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 开启aop操作 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <!-- 配置对象 --> <bean id="test01" class="cn.muriel.auto.aop.Test01"/> <bean id="test02" class="cn.muriel.auto.aop.Test02"/> </beans> /** * 测试代码 */ public class TestUtil { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("aop/aop.xml"); Test01 test01 = (Test01) applicationContext.getBean("test01"); test01.test01(); } }
- 基于aspectJ的xml配置
- AspectJ
- ioc
- 控制反转,把对象对创建不是通过new方式实现,而是交给spring配置创建类对象
- IOC和DI区别
- IOC:控制反转,把对象创建交给spring进行配置
- DI:依赖注入,向类里面的属性中设置值
- IOC和DI关系
- 依赖注入不能单独存在,需要在ioc基础之上完成操作
- ioc操作
- ioc的配置文件方式
<!-- 配置文件 --> <?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="userService" class="cn.xxx.auto.service.UserService"/> </beans> <!-- 测试代码 --> public class TestUtil { private static ApplicationContext applicationContext; public static void main(String[] args) { applicationContext = new ClassPathXmlApplicationContext("service/service.xml"); UserService userService = (UserService) applicationContext.getBean("userService"); userService.test(); }
- ioc的注解方式
- 什么是注解
- 代码里面特殊标记,使用注解可以完成功能
- 注解的写法
- @注解名称(属性名称=属性值)
- 注解的使用范围
- 类
- 方法
- 属性
- 常用注解
- @Controller:WEB层
- @Service:业务层
- @Repository:持久层
- @Component:类
- 注解创建对象
<!-- 导入基本的jar包和aop.jar包 --> <!-- 创建类、方法 --> <!-- 创建spring配置文件,引入约束 --> <?xml version="1.0" encoding="UTF-8" ?> <!-- http://www.springframework.org/schema/context/spring-context.xsd:用于注解的约束 --> <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"> <!-- bean definitions here --> <!-- 开启注解扫描:到包里面扫描类、方法、属性上面是否有注解 --> <context:component-scan base-package="cn.xxx.auto.pojo"/> <!-- 开启注解扫描:扫描属性上面的注解 <context:annotation-config></context:annotation-config>--> </beans> /** * 注解创建对象:在创建对象的类上面使用注解实现 */ @Component(value="user") //相当于<bean id="user" class="" /> @Scope(value="prototype")//默认为单实例,prototype为多实例 public class User { public void test(){ System.out.println("创建成功"); } } /** * 测试代码 */ public class TestUtil { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("pojo/pojo.xml"); User user = (User) applicationContext.getBean("user"); user.test(); }
- 注解注入属性(Autowired)
<!-- --> <?xml version="1.0" encoding="UTF-8" ?> <!-- http://www.springframework.org/schema/context/spring-context.xsd:用于注解的约束 --> <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"> <!-- 导入文件 --> <import resource="classpath:dao/dao.xml"/> <import resource="classpath:pojo/pojo.xml"/> <context:component-scan base-package="cn.xxx.auto.service"></context:component-scan> <!--<bean id="userService" class="cn.xxx.auto.service.UserService">--> <!-- 注入dao对象: name:service类里面属性名称 value:赋值给name的字符串 ref:赋值给name的对象,配置bean的id值 <property name="userDao" ref="userDao"/> </bean>--> </beans> /** * */ @Component(value = "userService") public class UserService { //在dao属性上面使用注解完成对象注入 @Autowired private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void addUser(User user) { userDao.insert(user); } } /** * */ public class TestUtil { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("service/service.xml"); UserService userService = (UserService) applicationContext.getBean("userService"); UserDao userDao = (UserDao) applicationContext.getBean("userDao"); User user = (User) applicationContext.getBean("user"); userService.setUserDao(userDao); userService.addUser(user); }
- 注解注入属性(Resource)
<!-- --> <?xml version="1.0" encoding="UTF-8" ?> <!-- http://www.springframework.org/schema/context/spring-context.xsd:用于注解的约束 --> <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"> <!-- 导入文件 --> <import resource="classpath:dao/dao.xml"/> <import resource="classpath:pojo/pojo.xml"/> <context:component-scan base-package="cn.xxx.auto.service"></context:component-scan> <!--<bean id="userService" class="cn.xxx.auto.service.UserService">--> <!-- 注入dao对象: name:service类里面属性名称 value:赋值给name的字符串 ref:赋值给name的对象,配置bean的id值 <property name="userDao" ref="userDao"/> </bean>--> </beans> /** * */ @Repository(value = "userDao") public class UserDao implements UserMapper { } /** * */ @Component(value = "userService") public class UserService { //在dao属性上面使用注解完成对象注入 //name属性值写注解创建dao对象的value值 @Resource(name = "userDao") private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void addUser(User user) { userDao.insert(user); } } /** * */ public class TestUtil { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("service/service.xml"); UserService userService = (UserService) applicationContext.getBean("userService"); UserDao userDao = (UserDao) applicationContext.getBean("userDao"); User user = (User) applicationContext.getBean("user"); userService.setUserDao(userDao); userService.addUser(user); }
- 什么是注解
- ioc的配置文件方式
- ioc底层原理使用技术
- xml配置文件
- dom4j解决xml
- 工厂设计模式
- 反射
/** * ioc底层原理 */ public class UserFactory { private String serviceId = "userService"; /** * (1)使用dom4j解析xml方法 * (2)使用反射创建对象 * * @return 返回UserService对象的方法 */ public UserService getUserService() { //导入dom4j.jar SAXReader saxReader = new SAXReader(); //获取指定xml文件 URL url = this.getClass().getClassLoader().getResource("service/service.xml"); try { Document document = saxReader.read(url); //获取根结点 Element rootElement = document.getRootElement(); //获取根结点下的子节点 List elements = rootElement.elements(); String serviceClass = ""; //遍历取出子节点 for (int i = 0; i < elements.size(); i++) { //获取子节点 Element element = (Element) elements.get(i); //获取子节点下的参数 Attribute idAttribute = element.attribute("id"); Attribute classAttribute = element.attribute("class"); if (serviceId.equals(idAttribute.getValue())) { serviceClass = classAttribute.getValue(); break; } } System.out.println(serviceClass); Class<?> newClass = Class.forName(serviceClass); return (UserService) newClass.newInstance(); } catch (DocumentException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } return null; } /** * 测试 * @param args */ public static void main(String[] args) { UserFactory service = new UserFactory(); UserService userService = service.getUserService(); userService.test(); } }
- spring是一站式框架
- spring在javaee三层架构中,每一层都提供不同的解决技术
- web层:SpringMvc
- service层:spring的ioc
- dao层:spring的jdbcTemplate
- spring在javaee三层架构中,每一层都提供不同的解决技术
- spring入门(ioc,service的创建)
- 导入jar包
- 做spring最基本功能时,只需要导入beans、core、context、expression这四个jar包
- 导入支持日志输出的jar包,commons-logging-1.2.jar
- 创建类,在类里面创建方法
public class UserService { public void test(){ System.out.println("获取成功"); } }
- 创建spring配置文件,配置创建类
- 建议放到src下面,官方建议applicationContext.xml
- 引入schema约束(spring/framework/reference/html/xsd-configuration.html)
- 写代码测试对象创建
- 导入jar包
- spring的bean管理(xml配置文件)
- bean是实例化的方式
- 使用类的无参数构造创建
<bean id="user" class="cn.xxx.auto.pojo.User"/>
- 使用静态工厂创建
public class UserFactory { public static User getUser() { return new User(); } } <!-- 配置文件 --> <!-- destroy-method:静态工厂中的静态方法 --> <bean id="user" class="cn.xxx.auto.factory.UserFactory" destroy-method="getUser"/>
- 使用实例工厂创建
public class UserFactory { public User getUser() { return new User(); } } <!-- 配置文件 --> <!-- factory-bean:实例工厂中的对象 factory-method:实例工厂中的方法 --> <bean id="userFactory" class="cn.xxx.auto.factory.UserFactory" destroy-method="getUser"/> <bean id="user" factory-bean="userFactory" factory-method="getUser" />
- 使用类的无参数构造创建
- bean标签常用属性
- id属性
- 起名称,id属性名称任意命名。
- 通过id值得到配置对象
- class属性
- 创建对象所在类的全路径
- name属性
- 功能与id属性一样
- 与id属性区别在于,id不可以包含特殊符号
- scope属性
- singleton:默认值。单例。获取都是同一个对象
- prototype:多例。获取是不同对象
- request:创建对象把对象放到request域里面
- session:创建对象把对象放到session域里面
- globalSession:创建对象把对象放到globalSession域里面
- id属性
- 属性注入方式
- 使用set方法注入
/** * 测试代码 */ public class TestUtil { private String obj;
public void setObj(String obj) { this.obj = obj; }
public void test(){
System.out.println("obj="+obj);
} public static void main(String[] args) { TestUtil testUtil = new TestUtil();
testUtil.setObj("obj");
test(); } } <!-- 使用有参数构造注入属性 --> <bean id="user" class="cn.muriel.mybatis.utils.TestUtil"> <!-- 使用有参构造注入 --> <property name="obj" value="obj"/> </bean> - 有参数构造注入
/** * 测试代码 */ public class TestUtil { public TestUtil(String obj) { System.out.println(obj); } public static void main(String[] args) { TestUtil testUtil = new TestUtil("obj"); } } <!-- 使用有参数构造注入属性 --> <bean id="user" class="cn.muriel.mybatis.utils.TestUtil"> <!-- 使用有参构造注入 --> <constructor-arg name="obj" value="obj"/> </bean>
- 使用接口注入(spring不支持)
- 使用set方法注入
- spring注入属性(有参构造和set方法)
- 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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userDao" class="cn.xxx.auto.dao.UserDao"></bean> </beans> <?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"> <!-- 导入文件 --> <import resource="classpath:dao/dao.xml"/> <bean id="userService" class="cn.xxx.auto.service.UserService"> <!-- 注入dao对象: name:service类里面属性名称 value:赋值给name的字符串 ref:赋值给name的对象,配置bean的id值 --> <property name="userDao" ref="userDao"/> </bean> </beans> public class UserService { //声明mapper对象 private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void addUser() { System.out.println("测试"); } } /** * 测试代码 */ public class TestUtil { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("service/service.xml"); UserService userService = (UserService) applicationContext.getBean("userService"); UserDao userDao = (UserDao) applicationContext.getBean("userDao"); userService.setUserDao(userDao); userService.addUser(); } }
- p名称空间注入
<?xml version="1.0" encoding="UTF-8" ?> <!-- 引入名称空间p:xmlns:p="http://www.springframework.org/schema/p" --> <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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userDao" class="cn.xxx.auto.dao.UserDao"></bean> </beans> <?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"> <!-- 导入文件 --> <import resource="classpath:dao/dao.xml"/> <bean id="userService" class="cn.xxx.auto.service.UserService" p:pname-ref="userDao> </bean> </beans> public class UserService { //声明mapper对象 private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void addUser() { System.out.println("测试"); } } /** * 测试代码 */ public class TestUtil { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("service/service.xml"); UserService userService = (UserService) applicationContext.getBean("userService"); UserDao userDao = (UserDao) applicationContext.getBean("userDao"); userService.setUserDao(userDao); userService.addUser(); } }
- spring注入复杂数据
- 数组
- list集合
- map集合
- 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="userDao" class="cn.xxx.auto.dao.UserDao"></bean> </beans> <?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="userService" class="cn.xxx.auto.service.UserService"> <!-- arrs: --> <property name="arrs"> <list> <value>1</value> <value>2</value> <value>3</value> </list> </property> <!-- list: --> <property name="list"> <list> <value>11</value> <value>22</value> <value>33</value> </list> </property> <!-- map: --> <property name="map"> <map> <entry key="username" value="aa"></entry> <entry key="password" value="bb"></entry> </map> </property> <!-- --> <property name="properties"> <props> <prop key="username">aa</prop> <prop key="password">bb</prop> </list> </property> </bean> </beans> public class UserService { private String[] arrs; private List<String> list; private Map<String,String> map; private Properties properties; public void setArrs(String[] arrs) { this.arrs = arrs; } public void setList(List<String> list) { this.list = list; } public void setMap(Map<String,String> map) { this.map = map; } public void setProperties(Properties properties) { this.properties = properties; } public void addUser() { System.out.println("arrs="+arrs); System.out.println("list="+list); System.out.println("map="+map); System.out.println("properties="+properties); } } /** * 测试代码 */ public class TestUtil { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("service/service.xml"); UserService userService = (UserService) applicationContext.getBean("userService"); UserDao userDao = (UserDao) applicationContext.getBean("userDao"); userService.setUserDao(userDao); userService.addUser(); } }
- bean是实例化的方式