1.Spring是一个轻量级的开源框架,非侵入性,基于Spring框架开发部依赖Spring的API,spring-core核心包包括IOC和依赖注入功能,spring-beans提供beanFactory,context继承Bean模块,类似JNDI注册方式访问对象,添加了国际化,事件传播,资源加载透明的创建上下文,spring-expression表达式语言
2.创建maven工程,主项目中packaging修改为pom,为管理类项目,添加spring-context依赖,创建子module,在子module的resources中编写spring的核心配置文件application.xml,在里面配置bean,bean标签的id唯一标识符,class全限定名称,init-method初始化方法,destroy-method销毁方法,在测试方法中new ClassPathXmlApplicationContext("application.xml")创建容器
3.primary属性优先使用的bean,depends-on被依赖的对象先创建,scope作用域,默认singleton单例容器启动就创建对象,prototype原型bean容器启动不创建对象,每次使用创建一个,request一次请求,session一次会话
4.bean的生命周期,容器启动,创建对象,属性赋值,init方法,对象使用,销毁方法
5.静态工厂配置bean用factory-method,实例工厂配置两个bean第一个为工厂,第二bean的factory-bean="工厂bean的id",factory-method="实例方法",implements FactoryBean<>接口配置一个标签,但是里面放的是泛型的对象
6.依赖注入,1.构造方法注入,在bean标签子标签<constructor-arg value="属性值" index="下标一般用name" name="属性名";2.set方法注入子标签中<property name="属性名" value="属性值"
<bean id="person" class="bean.Person"> <property name="id" value="1"/>//普通属性 <property name="likes">//数组 <array> <value>足球</value> <value>篮球</value> </array> </property> <property name="girlFriends"> <set> <value>李雷</value> <value>韩梅梅</value> </set> </property> <property name="dogs"> <list> <value>哈士奇</value> <value>田园犬</value> </list> </property> <property name="house"> <map> <entry key="bs" value="别墅"></entry> <entry key="lf" value="楼房"></entry> </map> </property> <property name="properties"> <props> <prop key="driver">com.mysql.jdbc.cj.Driver</prop> <prop key="url">mysql:jdbc://localhost:3306</prop> <prop key="username">root</prop> <prop key="password">root</prop> </props> </property> <property name="hobby" ref="hobby"/>//自定义类型ref指向一个bean的id </bean>
7,自动装配autowire属性,1no不自动装配2,byName根据名称,一致转配,不一致null不报错3.byType根据类型,没有null不报错多个抛异常4.default参照beans中的属性值,不能兼顾
8.注解@component,将当前类放入IOC容器中,在配置文件中开启组件扫描
<context:component-scan base-package="com.cjnode"/>,默认名称为首字母小写,可以用value给bean设置名称,@Controller@Service@Repository三层架构注解和@Component注解一致
9,@Value注解给属性赋值,@Autowired自动装配现根据类型再名称属性required=false表示没有不装配,辅助注解@Qualifer手动指定名称查找,@Resource也是自动装配是java包下的,Spring扩展了此注解,先根据名称再根据类型。
10,静态代理
public class UserDaoProxy implements UserDao { private UserDao userDao; public UserDaoProxy(UserDao userDao){ this.userDao = userDao; } @Override public void insert() { System.out.println("静态代理日志记录+insert"); userDao.insert(); } }
11.JDK动态代理
public class JDKProxy implements InvocationHandler { /** * invoke执行调用代理目标类的业务方法 * @param proxy 代理对象 * @param method 代理目标类的方法 * @param args 代理目标类方法参数 * @return 代理目标类的返回值 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("JDK动态代理的前置日志..."+method.getName()); Object resultVal = method.invoke(targetClass.newInstance(), args); return resultVal; } private Class targetClass; /** * 创建代理类对象,实现和代理目标类对象同一个父接口 * 三个参数1.代理目标类的类加载器,父接口,和代理类对象 * @return */ public Object getProxy(Class targetClass){ this.targetClass = targetClass; return Proxy.newProxyInstance(targetClass.getClassLoader(),targetClass.getInterfaces(),this); } }缺点必须实现InvocationHandler接口,才能调用Invoke方法
12,Cglib动态代理
public class CglibProxy implements MethodInterceptor { /** * intercept调用目标方法类似JDK中的Invoke() * @param o 代理类对象 * @param method 代理目标类方法 * @param objects 代理目标类方法参数 * @param methodProxy 代理方法对象 */ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("Cglib动态代理前置日志"+method.getName()); Object resultVal = method.invoke(targetClass.newInstance(), objects); return resultVal; } private Class targetClass; public Object getProxy(Class targetClass){ this.targetClass = targetClass; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(targetClass);//设置父类,继承代理目标类 enhancer.setCallback(this);//设置回调,调用代理类中的intercept()方法 return enhancer.create(); } }
13.AOP面向切面编程1.切面,跨越多个模块的零散工程,使其成为一个独立的应用于其他模块中的模块例如在serviceimpl包下所以方法执行前2.通知Advice切面完成的功能3.连接点具体位置例如userDaoImpl的insert()方法执行前4.切点多个连接点组成,所以insert()方法执行前
引入依赖spring-aspects,在application.xml中引入aop:config命名空间
<aop:config> <aop:pointcut id="exp" expression="execution(* dao.impl.*.*(..))"/>//配置公共切点表达式 <aop:aspect ref="log"> <!-- execution(修饰符 返回值类型 方法所在包名.类名.方法名(参数)) execution(* * * *(..))第一个*不限制修饰符和返回值,二*不限制包,三*不限制类,四*不限制方法,..不限制参数 --> <aop:before method="beforeMethod" pointcut="execution(public void com.bjpowernode.dao.impl.UserDaoImpl.insert())"/> <aop:after-returning method="returnMethod" pointcut="execution(* *dao.impl.*impl.*(..)" returning="result"/> </aop:aspect> </aop:config>
环绕通知
public void aroundMethod(ProceedingJoinPoint proceedingJoinPoint){ System.out.println("前置通知"); try { Object result = proceedingJoinPoint.proceed(); System.out.println("返回通知"+result); } catch (Throwable e) { System.out.println("异常通知"+e); } System.out.println("后置通知"); }
注解配置组件<aop:aspectj-autoproxy/>开启aop注解,在切面类上配置@Compnent@@Aspect方法上@before@AfterReturning(value = "execution(* dao.*.*impl(..))", returning = "result")
@AfterThrowing@Alfter@Around()
切点优先级:配置多个切面时,前置通知配置在前先执行,后置通知配置在前后执行,order属性为正整数越小优先级越高