赞
踩
maven配置依赖的网站在mvnrepositoty.com这个网站
关于代理:代理的好处就在于即使依赖其他文件的方法也不用频繁改动代码
静态代理:
缺点:跟目标对象一样实现了抽象业务的接口,一般接口改变这个类也必须要跟着改变
动态代理:
1.proxy创建
缺点:不能实现非实现接口的类
创建一个proxy代理实现InvocationHandler这个类的方法
- package com.test;
-
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
-
- public class JdkProxy implements InvocationHandler {
-
-
- private Object object;
-
- public JdkProxy() {
- }
-
- public JdkProxy(Object object) {
- this.object = object;
- }
-
- private Object createProxy(Object object){
-
- this.object= object;
-
- return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
-
-
- // Proxy.newProxyInstance(this.object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
- }
-
-
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-
-
- Object invoke = method.invoke(this.object, args);
-
- if (method.getName().equals("nmdwsm")){
- System.out.println("nmdwsm");
- }
-
- return invoke;
-
- }
- }
2.cglib创建
优点:能代理没有实现接口的类和实现接口的类
创建一个cglib代理实现MtehodInterceptor这个类的方法
- package com.entor.jdkproxy;
-
- import org.springframework.cglib.proxy.Enhancer;
- import org.springframework.cglib.proxy.MethodInterceptor;
- import org.springframework.cglib.proxy.MethodProxy;
-
- import java.lang.reflect.Method;
-
- public class Cglib implements MethodInterceptor {
-
- private Object targetObject;
- /**
- *@describe 创建没有实现接口的代理对硝基
- **/
- public Object createTargetObject(Object o){
- this.targetObject = o;
-
- Enhancer enhancer = new Enhancer();
-
- enhancer.setSuperclass(this.targetObject.getClass());
-
- enhancer.setCallback(this);
-
- return enhancer.create();
-
-
- }
-
-
- @Override
- public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
-
- Object invoke = method.invoke(this.targetObject, objects);
-
- if (method.getName().equals("rent")){
- check();
- }
- return invoke;
- }
-
-
-
- public void check(){
- System.out.println("检查");
- }
- }
虽然proxy代理创建的理念是每个类都能有一个接口实现,但是还是不太现实,所以才会有cglib的出现,本质上这两个代理都是用反射的方法获取到对象
关于aop的概念我觉得可以参考这篇10年前的博文Spring AOP概念理解 _宏桥科技------PowerBridge-CSDN博客
applicationContext.xml中配置aop,需要注意的是切点配置的是全类名加方法名,在使用的时候无论如何最后面的两个点之间分别代表的是类和类里面的方法。
- <!--目标对象-->
- <bean id="userService" class="com.entor.aop.impl.UserServiceImpl" lazy-init="true"></bean>
- <!--切面对象-->
- <bean id="aop" class="com.entor.aop.Aop" lazy-init="true"></bean>
- <!--配置切面-->
- <!-- ref引用之前配置bean对象的id-->
- <aop:config>
- <aop:aspect id="aopAspect" ref="aop">
- <!-- 第一个*代表任意返回值 空格一定要有 后面的*全部文件或者全部方法,全部的意思 -->
- <!-- <aop:pointcut id="method" expression="execution(* com.entor.aop.UserService.update())"/>-->
- <!-- 这些方法都是单个连接点,这些连接点组合在一起构成切入点-->
- <aop:pointcut id="method" expression="execution(* com.entor.aop.UserService.*(..))"/>
- <!-- <aop:pointcut id="method" expression="execution(* com.entor.aop.*.*(..))"/>-->
- <!--前置通知,把切面的check()方法植入到method的前面-->
- <aop:before method="check" pointcut-ref="method"></aop:before>
- <!--前置通知,把切面的check()方法植入到method的后面-->
- <aop:after method="log" pointcut-ref="method"></aop:after>
- </aop:aspect>
- </aop:config>
maven项目自动导入依赖
在pom.xml文件里面先加一个dependencies标签,在artifactid标签输入spring点选webmvc之后按照org.springframework进行配置就能自动引进依赖了
使用aop还需要配置其他依赖
-
- <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjweaver</artifactId>
- <version>1.9.7</version>
- <scope>runtime</scope>
- </dependency>
-
- </dependencies>
-
你同样可以去https://mvnrepository.com/artifact/org.aspectj/aspectjweaver/1.9.7这里拿到依赖然后配置,搜索aspect就行了
注意:记得删除删除aspect的作用域就是scope标签
获取对象
-
- // 使用spring框架的aop实现动态代理
- ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.aop.xml");
- //
- // UserService bean1 = (UserService) context.getBean("userService");
- //
- // bean1.update();
- /**
- *@describe 用接口动态获取获取
- **/
- UserService userService = context.getBean(UserService.class);
- userService.update();
在这里会自动在连接点位置输出我们定义的两个通知
通过注解的方式进行aop
- package com.entor.annotation;
-
- import org.aspectj.lang.annotation.After;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
- import org.aspectj.lang.annotation.Pointcut;
- import org.springframework.context.annotation.EnableAspectJAutoProxy;
- import org.springframework.stereotype.Component;
-
- @Component
- @Aspect
- @EnableAspectJAutoProxy//开启自动aop代理
- public class Aop {
-
- @Pointcut("execution(* com.entor.annotation.*.*(..))")
- public void method() {
-
- }
- /**
- *@describe 前置,该方法在切入点方法前使用
- **/
- @Before("method()")
- private void check() {
- System.out.println("检查");
- }
- /**
- *@describe 后置,该方法在切入点方法后使用
- **/
- @After("method()")
- private void log() {
- System.out.println("记录");
- }
- }
开启扫描,如果不开启EnableAspectJAutoProxy代理的话还有在pom.xml文件里面进行配置
- <context:component-scan base-package="com.entor.annotation"></context:component-scan>
- <!-- 开启aop自动代理-->
- <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
- package com.entor.annotation;
-
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class Test {
-
- public static void main(String[] args) {
-
- /**
- *@describe getbean其实是多态的一种实现,在开发中我们一般用id来选择类
- **/
- ClassPathXmlApplicationContext cla = new ClassPathXmlApplicationContext("/applicationContext.aop-annotation.xml");
-
- UseService bean =cla.getBean(UseService.class);
- bean.delete();
- }
-
- }
配置spring数据库连接池,需要去官网下载依赖
把依赖放到pom.xml文件当中后继续去查找这个数据库连接池的依赖,现在市面上有几大数据库连接池,这里的数据库连接池只是用来练习用,已经停止更新了
这里是配置数据库连接池的一些标签和值,如果要使用的话还要更改地址,所以说我还是喜欢注解,xml标签多了简直是难以维护
还有配置mysql的依赖,也就是mysql数据库的驱动
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>5.1.43</version>
- </dependency>
这是配置数据库连接池的文档配置
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
-
- <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
- <property name="url" value="jdbc:mysql://localhost:3306/user_test?useUnicode=true&useSSL=false
- &characterEncoding=utf-8&serverTimezone=Asia/Shanghai"></property>
-
- <property name="username" value="root"></property>
- <property name="password" value="root"></property>
-
- </bean>
-
-
- <!--配置事务管理器-->
- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"></bean>
-
-
- <!-- 配置事务传播特性,哪些方法需要开事务,触发连续的事务时会把触发的方法归类到一个事务中-->
- <tx:advice id="advice" transaction-manager="transactionManager">
- <tx:attributes>
- <!-- 需要加事务的属性,方法名以哪些开头的都要开启事务,除此之外的方法不需要开启事务-->
- <tx:method name="add*" propagation="REQUIRED"></tx:method>
- <tx:method name="update*" propagation="REQUIRED"></tx:method>
- <tx:method name="delete*" propagation="REQUIRED"></tx:method>
- <tx:method name="save*" propagation="REQUIRED"></tx:method>
- <tx:method name="modify*" propagation="REQUIRED"></tx:method>
- <tx:method name="insert*" propagation="REQUIRED"></tx:method>
- <tx:method name="*" propagation="NOT_SUPPORTED" read-only="true"></tx:method>
- </tx:attributes>
-
-
- </tx:advice>
-
-
- <aop:config>
-
- <aop:pointcut id="pointcut" expression="execution(* com.entor.service.impl.*.*())"></aop:pointcut>
- <aop:advisor advice-ref="advice" pointcut-ref="pointcut"></aop:advisor>
-
- </aop:config>
基本上打一遍就差不多了。
注解开发实体类
同样我们还要导入相关的依赖
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <version>1.18.16</version>
- </dependency>
之后在实体类上面进行注解
- @Data//这里是配置了实体类里面的get和set方法
- @NoArgsConstructor//这里定义了实体类里面的无参构造方法
- @AllArgsConstructor//这里配置了实体类的全参构造方法
- public class User {
这样就不用再手动get和set了,但是你如果需要其他构造方法你需要自己给出
- <!-- 需要加事务的属性,方法名以哪些开头的都要开启事务,除此之外的方法不需要开启事务
- 默认runtimeexeception异常回滚,其他异常不回滚,但是可以通过rollback属性和no-rollback-for属性修改规则
比如
<tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.RuntimeException"></tx:method>
或者
<tx:method name="update*" propagation="REQUIRED" no-rollback-for="java.lang.RuntimeException"></tx:method>
注解开发
- /**
- *@describe 整个类都开启事务注解,只能放在公共的方法里面
- **/
- @Transactional(rollbackFor = Exception.class)
- @Service
- public class UserServiceImpl implements UserService {
- <!-- 通过注解的方式管理事务的传播特性-->
-
- <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
配置注解开发后我们不需要事务的传播特性和aop切面和切点的引入了,所以配置文件变为
-
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
- <property name="password" value="root"></property>
- <property name="username" value="root"></property>
- <property name="url" value="jdbc:mysql://localhost:3306/user_test?useUnicode=true&
- useSSL=false&characterEncoding=utf-8&serverTimeZone=Asic/Shanghai"></property>
- <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
- </bean>
-
-
- <!--配置事务管理器-->
- <!-- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"></bean>-->
-
- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <!-- 通过注解的方式管理事务的传播特性-->
-
- <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
-
- <context:component-scan base-package="com.entor"></context:component-scan>
- <context:annotation-config></context:annotation-config>
-
- <!-- /**-->
- <!-- *@describe 配置模板工具类同时指定数据源-->
- <!-- **/-->
- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
无注解开发,把配置文件变为一个类就行了
- package com.entor2;
-
- import org.springframework.beans.factory.annotation.Qualifier;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.Lazy;
- import org.springframework.context.annotation.Scope;
-
- /**
- * @describe 作用在类上面,等价于一个applicationContext.xml文件
- **/
- @Configuration
- public class SpringConfig {
- /**
- * @describe 作用在方法上,相当于配置文件当中id = bean4 class = com.entor.Bean4
- **/
-
- @Bean(value = "bean44")
- /**
- *@describe 数组bean的单例还是多
- **/
- @Scope
- /**
- *@describe 数组加载模式是否为懒加载
- **/
- @Lazy
- public Bean4 bean4() {
- return new Bean4();
- }
-
- @Bean
- public Bean5 bean5() {
- return new Bean5();
- }
-
- @Bean
- public Bean5 bean52() {
- return new Bean5();
- }
-
- /**
- * @describe 通过方法参数注入对象,先根据参数类型去查找,再通过参数名称查找
- * 也可以结合qualifier指定名称获取
- **/
-
- @Bean
- public Bean5 bean53(@Qualifier("bean52") Bean5 bean) {
- return bean;
- }
- }
通过普通方法new的对象在其他bean被调用的时候只会创建一次,和自己new的效果是一样的
@Import(ImportSelectTest.class)
半写死的代码
- package com.entor2;
-
- import org.springframework.context.annotation.ImportSelector;
- import org.springframework.core.type.AnnotationMetadata;
-
- public class ImportSelectTest implements ImportSelector {
-
- /**
- *@describe 导入选择器可以选择性导入多个bean对象
- **/
-
- @Override
- public String[] selectImports(AnnotationMetadata annotationMetadata) {
- return new String[]{"com.entor2.Bean6"};
-
-
- }
- }
写活的代码
- package com.entor2;
- import org.springframework.context.annotation.ImportSelector;
- import org.springframework.core.type.AnnotationMetadata;
- import java.io.IOException;
- import java.util.Properties;
- public class ImportSelectTest2 implements ImportSelector {
- private static String[] beanArry;
- static {
- Properties properties = new Properties();
- /**
- *@describe 在配置文件中配置
- **/
- try {
- properties.load(ImportSelectTest2.class.getResourceAsStream("bean.properties"));
- String bean = properties.getProperty("bean");
-
- if (bean!=null){
- beanArry= bean.split(",");
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- @Override
- public String[] selectImports(AnnotationMetadata annotationMetadata) {
- return beanArry;
-
- }
- }
AOP使用
- package com.entor.sys.log;
-
-
- import lombok.extern.slf4j.Slf4j;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.Signature;
- import org.aspectj.lang.annotation.AfterReturning;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
- import org.aspectj.lang.annotation.Pointcut;
- import org.springframework.stereotype.Component;
- import org.springframework.web.context.request.RequestContextHolder;
- import org.springframework.web.context.request.ServletRequestAttributes;
-
- import javax.servlet.http.HttpServletRequest;
- import java.util.Enumeration;
-
- @Component
- @Aspect
- @Slf4j
- public class LogAspect {
-
- @Pointcut("execution(* com.entor.sys.controller.*.*(..))")
- public void webLog(){}
-
-
- @Before("webLog()")
- public void doBefore(JoinPoint joinPoint) throws Throwable {
-
-
-
- // 接收到请求,记录请求内容
- ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
- HttpServletRequest request = attributes.getRequest();
- // 记录下请求内容
- log.info("URL : " + request.getRequestURL().toString());
- log.info("HTTP_METHOD : " + request.getMethod());
- log.info("IP : " + request.getRemoteAddr());
- Enumeration<String> enu = request.getParameterNames();
- while (enu.hasMoreElements()) {
- String name = (String) enu.nextElement();
- log.info("name:{},value:{}", name, request.getParameter(name));
- }
- System.out.println("________________");
- Signature signature = joinPoint.getSignature();
- Class declaringType = signature.getDeclaringType();
-
-
- }
- @AfterReturning(returning = "ret", pointcut = "webLog()")
- public void doAfterReturning(Object ret) throws Throwable {
- // 处理完请求,返回内容
- log.info("RESPONSE : " + ret);
- }
-
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。